Tartu tiedostopääte tiedostoon

Kuinka saan tiedostopääte bashilta? Tässä yritin:

filename=`basename $filepath` fileext=${filename##*.} 

Tällöin saan bz2 -laajennuksen polulta /dir/subdir/file.bz2, mutta minulla on ongelma polulla /dir/subdir/file-1.0.tar.bz2.

Haluaisin mieluummin ratkaisun, jossa käytetään vain bash-tiedostoa ilman ulkoista ohjelmia, jos se on mahdollista.

Kysymykseni selventämiseksi luoin bash-komentosarjan, jolla jokin arkisto purettiin vain yhdellä komennolla extract path_to_file. tiedoston purkaminen määritetään komentosarjan avulla näkemällä sen pakkaus- tai arkistointityyppi, joka voi olla .tar.gz, .gz, .bz2 jne. Mielestäni tämän pitäisi liittyä merkkijonon manipulointiin, esimerkiksi jos saan laajennuksen .gz minun pitäisi tarkistaa, onko siinä merkkijono .tar ennen .gz – jos on, laajennuksen tulisi olla be .tar.gz.

Kommentit

  • file = ” /dir/subdir/file-1.0.tar.bz2

; echo $ {file ## *.} tulostaa ’ .bz2 ’ tänne. Mikä on tulos, jonka ’ odotat uudelleen?

  • Tarvitsen .tar.bz2
  • aiheeseen liittyvää : Pura tiedostonimi ja laajennus Bashissa .
  • Vastaa

    Jos tiedoston nimi on file-1.0.tar.bz2, laajennus on bz2. Menetelmä, jota käytät laajennuksen purkamiseen (fileext=${filename##*.}), on täysin kelvollinen¹.

    Kuinka päätät laajennuksen olevan tar.bz2 eikä bz2 tai 0.tar.bz2? Sinun on ensin vastattava tähän kysymykseen. Sitten voit selvittää, mitä shell-komento vastaa määritystesi.

    • Yksi mahdollinen määrittely on, että laajennusten on aloitettava kirjaimella. Tämä heuristinen tiedosto epäonnistuu muutamalle yleiselle laajennukselle, kuten 7z, jota voidaan parhaiten käsitellä erityistapauksena. Tässä ”bash / ksh / zsh-toteutus:

      basename=$filename; fileext= while [[ $basename = ?*.* && ( ${basename##*.} = [A-Za-z]* || ${basename##*.} = 7z ) ]] do fileext=${basename##*.}.$fileext basename=${basename%.*} done fileext=${fileext%.} 

      POSIX-siirrettävyys edellyttää, että case -lauseke mallien sovittamiseksi.

      while case $basename in ?*.*) case ${basename##*.} in [A-Za-z]*|7z) true;; *) false;; esac;; *) false;; esac do … 
    • Toinen mahdollinen erittely on, että jotkut Laajennukset merkitsevät koodauksia ja osoittavat, että tarvitaan lisää strippauksia. Tässä ”sa bash / ksh / zsh -toteutus (vaatii shopt -s extglob bashin alla ja setopt ksh_glob zsh: n alla):

      basename=$filename fileext= while [[ $basename = ?*.@(bz2|gz|lzma) ]]; do fileext=${basename##*.}.$fileext basename=${basename%.*} done if [[ $basename = ?*.* ]]; then fileext=${basename##*.}.$fileext basename=${basename%.*} fi fileext=${fileext%.} 

      Huomaa, että tämä pitää 0 laajennuksena tiedostossa file-1.0.gz.

    ¹ ${VARIABLE##SUFFIX} ja siihen liittyvät rakenteet ovat POSIXissa , joten he työskentelevät missä tahansa muussa kuin antiikkisessa Bourne-tyylisessä kuoressa, kuten tuhka, bash, ksh tai zsh.

    Kommentit

    • joiden pitäisi ratkaistaan tarkistamalla, onko merkkijono edellisen . -tunnisteen tyyppi on arkistotyyppi, esimerkiksi tar, jos se ei ole arkistotyyppi kuten 0 iteroinnin pitäisi päättyä.
    • @uray: se toimii tässä nimenomaisessa tapauksessa, mutta se ’ ei ole yleinen ratkaisu Harkitse Maciej ’ esimerkkiä .patch.lzma . Parempi heur istic olisi harkita merkkijonoa viimeisen . -merkin jälkeen: jos se ’ sa-pakkausliite (.7z, .bz2, .gz, …), jatka strippaamista.
    • @NoamM Mikä oli vikaa sisennyksessä? Se ’ rikkoo ehdottomasti muokkauksesi jälkeen: kaksinkertaisesti sisäkkäinen koodi on sisennys sama kuin yksitellen sisäkkäinen.

    Vastaa

    Voit yksinkertaistaa asioita tekemällä pelkän mallin vastaavuuden tiedostonimelle sen sijaan, että purat laajennuksen kahdesti:

    case "$filename" in *.tar.bz2) bunzip_then_untar ;; *.bz2) bunzip_only ;; *.tar.gz) untar_with -z ;; *.tgz) untar_with -z ;; *.gz) gunzip_only ;; *.zip) unzip ;; *.7z) do something ;; *) do nothing ;; esac 

    Kommentit

    • Tämä ratkaisu on kauniisti yksinkertainen.

    Vastaa

    $ echo "thisfile.txt"|awk -F . "{print $NF}" 

    Kommentteja tähän: http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/

    kommentit

    • ei toimi .tar.gz -laajennuksella
    • No .tar .gz on oikeastaan terva gzip-tiedoston sisällä, joten se toimii siinä mielessä, että se poistaa gz-laajennuksen gzip-tiedostosta.

    Vastaa

    Tässä on minun laukaukseni: Käännä pisteet uudelle riville, vie tail, hae viimeinen rivi:

    $> TEXT=123.234.345.456.456.567.678 $> echo $TEXT | tr . \\n | tail -n1 678 

    vastaus

    Eräänä päivänä olen luonut nuo hankalat toiminnot:

    # args: string how_many function get_last_letters(){ echo ${1:${#1}-$2:$2}; } function cut_last_letters(){ echo ${1:0:${#1}-$2}; } 

    Olen havainnut tämän suoraviivan lähestymistavan, joka on erittäin hyödyllinen monissa tapauksissa, ei vain silloin, kun se käy Tietoja laajennuksista.

    Laajennusten tarkistamiseen – Se on yksinkertainen ja luotettava

    ~$ get_last_letters file.bz2 4 .bz2 ~$ get_last_letters file.0.tar.bz2 4 .bz2 

    Laajennuksen katkaisu:

    ~$ cut_last_letters file.0.tar.bz2 4 file.0.tar 

    Laajennuksen muuttaminen:

    ~$ echo $(cut_last_letters file.0.tar.bz2 4).gz file.0.tar.gz 

    Tai jos haluat ”käteviä toimintoja:

    ~$ function cut_last_letters_and_add(){ echo ${1:0:${#1}-$2}"$3"; } ~$ cut_last_letters_and_add file.0.tar.bz2 4 .gz file.0.tar.gz 

    PS Jos pidit näistä funktioista tai pidit niitä hyödyllisinä, katso tämä viesti 🙂 (ja toivottavasti lisää kommentti).

    Vastaa

    echo ${filename#$(echo $filename | sed "s/\.[^[:digit:]].*$//g;")} 

    Esimerkiksi:

    Kommentit

    • Ei toimi kaikissa tapauksissa. Kokeile ’ foo.7z ’
    • Tarvitset lainausmerkkejä ja käytä paremmin printf jos tiedostonimi sisältää taaksepäin viivan tai alkaa -: "${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
    • @axel_c : oikea, ja olen ’ toteuttanut saman spesifikaation kuin Maciej esimerkkinä. Mitä heuristista ehdotat, että ’ on parempi kuin ”alkaa kirjaimella”?
    • @Gilles: Luulen vain, että ’ ei ole ratkaisu, ellet käytä ennalta laskettua luetteloa tunnetuista laajennuksista, koska laajennus voi olla mikä tahansa.

    Vastaa

    jackmanin tapauskohtainen vastaus on melko hyvä ja kannettava, mutta jos haluat vain tiedostonimen ja laajennuksen muuttujaan, olen löytänyt tämän ratkaisun:

    INPUTFILE="$1" INPUTFILEEXT=$( echo -n "$INPUTFILE" | rev | cut -d"." -f1 | rev ) INPUTFILEEXT=$( echo -n $INPUTFILEEXT | tr "[A-Z]" "[a-z]" ) # force lowercase extension INPUTFILENAME="`echo -n \"$INPUTFILE\" | rev | cut -d"." -f2- | rev`" # fix for files with multiple extensions like "gbamidi-v1.0.tar.gz" INPUTFILEEXT2=$( echo -n "$INPUTFILENAME" | rev | cut -d"." -f1 | rev ) if [ "$INPUTFILEEXT2" = "tar" ]; then # concatenate the extension INPUTFILEEXT="$INPUTFILEEXT2.$INPUTFILEEXT" # update the filename INPUTFILENAME="`echo -n \"$INPUTFILENAME\" | rev | cut -d"." -f2- | rev`" fi 

    Se toimii vain kaksoislaajennuksilla ja ensimmäisen on oltava ”terva”.

    Mutta voit vaihtaa ”terva” -testirivin merkkijonotestillä ja toistaa korjauksen useita kertoja .

    vastaus

    olen ratkaissut sen tällä tavalla:

    filename=`basename $filepath` fileext=${filename##*.} fileext2=${filename%.*} fileext3=${fileext2##*.} if [ "$fileext3" == "tar" ]; then fileext="tar."$fileext fi 

    mutta tämä toimii vain tunnetulle arkistointityypille, tässä tapauksessa vain tar

    Vastaa

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *