bash: Kuinka palautat tiedostotunnisteet?

Haluan kirjoittaa komentosarjan palauttamaan vain syötetiedoston nimen laajennuksen. Esimerkiksi textfile.txt pitäisi palauttaa txt.

Olen ”uusi Linuxille ja bashille ja I” m yrittää oppia kirjoittamaan komentosarjoja. Kiitos!

Kommentit

  • Katso myös stackoverflow.com/questions/965053/…
  • Mikä on linux-4.2.3.tar.xz -tiedostotunniste, jonka voit ladata osoitteesta kernel.org ? Mikä on /bin/bash -tiedostotunniste, joka on varmasti käytettävissä järjestelmässäsi? Tiedät, että " -tiedostotunnisteen " käsite on melko vieras Linuxissa. Pisteen jälkeisellä osalla on hyvin vähän merkitystä järjestelmälle – se on pikemminkin vihje käyttäjälle siitä, mitä hän voi odottaa tiedostosta. Ja tämä vihje voi olla valhe tai väärä.

Vastaus

Kuoressa, esimerkiksi bash, on monia merkkijonon käsittely -ominaisuudet. Yhden niistä avulla voit poistaa kaiken tiettyyn malliin saakka:

${VAR##GLOB} 

Yllä oleva syntaksi poistaa kaiken muuttujasta $VAR globin ensimmäiseen otteluun GLOB. Joten voit tulostaa tiedoston laajennuksen ilman sen nimeä seuraavasti:

$ file="file.txt" $ echo ${file##*.} txt 

Huomaa, että tämä voi käsitellä myös useampaa kuin yhtä ”laajennusta”:

$ file="file.new.txt" $ echo ${file##*.} txt 

Jos et halua sitä, käytä sen sijaan yhtä #, joka poistaa lyhimmän vastaavuuden pisimmistä:

$ echo ${file#*.} new.txt 

Voit suorittaa tämän kaikissa hakemiston tiedostoissa seuraavasti:

$ ls file.avi file.pdf file.png file.txt $ for file in *; do echo "$file : ${file##*.}"; done file.avi : avi file.pdf : pdf file.png : png file.txt : txt 

Ja täydellisyyden vuoksi voit myös saada tiedostonimen ilman sen laajennusta käyttämällä ${file%.*}:

$ for file in *; do echo "$file : ${file##*.} : ${file%.*}"; done file.avi : avi : file file.pdf : pdf : file file.png : png : file file.txt : txt : file 

Kommentit

  • tämä ei toimi ' ei toimi esimerkiksi foo / .git / bar / baz luulen että voisit tehdä kaiutestin.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} '
  • @PaulM mitä tarkoitat? Se ' sa-tiedosto, jolla ei ole laajennusta, mitä odotat saavasi siitä?
  • echo " / foo /var/.git/foo/bar.bz" | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} ' == > > bz
  • @PaulM file="/foo/var/.git/foo/bar.bz"; echo "${file##*.}": bz. En näe ' ongelmaa.

Vastaa

-parametrilaajennuksella :

$ x="textfile.txt" $ echo ${x##*.} txt 

${parameter##word} kuvio poistaa suurimman etuliitteen, joka vastaa word (kaikki paitsi tiedoston loppu).

Vastaa

Hyvin yksinkertainen bash-komentosarja, joka voi tehdä mitä haluat, on seuraava:

#!/usr/bin/env bash echo "$1" | awk -F "." "{print $NF}" 

Komentosarja kutsutaan nimellä script.sh test.txt, ja mitä se tekee, on

  • se tulostaa $1 tiedostoon stdout. $1 on komentosarjalle annettu ensimmäinen parametri, tässä tapauksessa test.txt.

  • echo: n vakiolähtö johdetaan stdin: iin awk, joka jakaa merkkijonon (test.txt) . -kohdassa ja tulostaa sitten jaon viimeisen elementin (txt tässä tapauksessa).

Vain pieni huomautus, tämä voidaan tehdä yhden linjan kanssa, koska se on melko yksinkertainen tehtävä:

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

kommentit

  • Sinun on lisättävä lainausmerkkejä $1 -kohdan ympärille, tai saatat rikkoa välilyöntejä sisältävien tiedostojen nimiä.
  • tämä ei toimi ' ei sellaisissa asioissa kuin foo / .git / bar / baz. Luulen, että voisit tehdä echo test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '.' ' {print $ NF} '

vastaus

#!/bin/bash my_file=`basename "$1"` # get full file name as a script parameter and strip the path my_extension="${my_file##*.}" my_file="${my_file%.*}" # will return base file name before the extension echo "$my_file" echo "$my_extension" 

Suorita:

./script.sh index.html 

Lähtö:

index html 

Lisätietoja: Shell-parametrilaajennus | gnu.org

vastaus

Tätä varten on otettava huomioon useita varoituksia:

  • foo.d/bar -tiedostolla ei ole laajennusta, se ei ole foo -tiedosto, jolla on .d/bar -laajennus.
  • voit myös harkita, että .bashrc ei ole laajennusta
  • . ja .. erikoishakemistotiedostoja tulisi todennäköisesti käsitellä erikseen ja niiden ei katsota olevan laajennuksia.
  • mitä laajennus file.tar.gz? gz tai tar.gz? Entä holiday.picture.jpg tai bash-4.4?
  • Mitä palautat foo.d/? Tyhjä vai d?

Täällä:

#! /bin/sh - for file do case ${file##*/} in (?*.*) ext=${file##*.};; (*) ext=;; esac printf "%s\n" "$ext" done 

Kommentit

  • Erinomainen vastausten käsittely myös tavallisissa huomautuksissa ja hyödyllisessä koodissa etenkin funktiona.

Vastaa

Annan vielä joitain vaihtoehtoja, jos sinulla on sed tai Perl:

 #!/bin/bash ext=$(<<<"$1" sed -n "s/^[^.]*\.//p") printf "Extension: $ext\n" ext=$(<<<"$1" perl -ne "s/^.*?\.//&&print") printf "Extension: $ext\n" exit 0  
  • s/^[^.]*\.//p muodossa sed ja s/^.*?\.//&&print ryhmässä perl: yritä korvata lyhin merkkijono, joka ei ole ., jota seuraa merkin alussa . -merkki; jos korvaaminen onnistui, tulosta korvaamisen tulos;
 % bash script.sh file.bin Extension: bin Extension: bin  

Vastaa

Ole varovainen. Unix / Linuxissa (ja MacOS) ”tiedostonimen laajennus” on vain informatiivinen (jos niin paljon). Sinulla voi olla täydellinen Perl-komentosarja nimeltä photo.gif tai GIF-tiedosto poem.txt. Tai jopa tiedosto nimeltä some.txt.png.

Kommentit

  • Se ' aivan yhtä informatiivista MS Windowsissa, se ' vain, että siellä oletuskuoriohjelma antaa vahvempia oletuksia laajennuksesta – sisällön pariliitosta, ja jos nimeämisen ja sisällön ristiriita, koko asia alkaa vain huutaa virheitä, köyhiä.

Vastaa

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