bash: jak zwracasz rozszerzenia plików?

Chcę napisać skrypt zwracający tylko rozszerzenie nazwy pliku wejściowego. Na przykład textfile.txt powinno zwrócić txt.

Jestem nowy w Linuksie i bashu, a ja „m próbując nauczyć się pisać podstawowe skrypty. Dzięki!

Komentarze

  • Zobacz także stackoverflow.com/questions/965053/…
  • Jakie jest rozszerzenie pliku linux-4.2.3.tar.xz, który można pobrać z kernel.org ? Jakie rozszerzenie pliku /bin/bash jest z pewnością dostępne w Twoim systemie? Widzisz, koncepcja ” rozszerzenia pliku ” jest dość obca w Linuksie. Część za kropką ma bardzo małe znaczenie dla systemu – jest raczej wskazówką dla użytkownika, czego może się spodziewać po tym pliku. I ta wskazówka może kłamać lub być błędna.

Odpowiedź

Powłoka, na przykład bash, ma wiele manipulacja napisami . Jedna z nich pozwala usunąć wszystko do podanego wzorca:

${VAR##GLOB} 

Powyższa składnia usuwa wszystko ze zmiennej $VAR do pierwszego dopasowania globu GLOB. Aby więc wydrukować rozszerzenie pliku bez jego nazwy, możesz zrobić:

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

Pamiętaj, że może to również dotyczyć więcej niż jednego „rozszerzenia”:

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

Jeśli tego nie chcesz, użyj zamiast tego jednego #, co spowoduje usunięcie najkrótszego dopasowania z najdłuższych:

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

Teraz, aby uruchomić to na wszystkich plikach w katalogu, możesz zrobić:

$ 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 

Ponadto, aby zapewnić kompletność, nazwę pliku można również pobrać bez rozszerzenia, używając ${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 

Komentarze

  • to nie ' nie działa w przypadku takich rzeczy jak foo / .git / bar / baz Myślę, że mógłbyś zrobić test echo.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '. ' ' {print $ NF} '
  • @PaulM co masz na myśli? Ten ' plik bez rozszerzenia, czego można by się po nim spodziewać?
  • 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. Nie ' nie widzę problemu.

Odpowiedź

Z rozszerzeniem parametrów :

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

${parameter##word} usuwa największy przedrostek, który pasuje do word (wszystko oprócz końcówki pliku).

Odpowiedź

Bardzo prosty skrypt basha, który mógłby zrobić to, co chcesz, byłby następujący:

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

Skrypt jest wywoływany jako script.sh test.txt, a robi to

  • wypisuje $1 na standardowe wyjście. $1 to pierwszy parametr przekazywany skryptowi, w tym przypadku test.txt.

  • wyjście standardowego wyjścia echo jest przesyłane potokiem do standardowego wejścia dla awk, które dzieli ciąg (test.txt) na ., a następnie drukuje ostatni element podziału (w tym przypadku txt).

Tylko mała uwaga, można to zrobić za pomocą jednej linijki, ponieważ jest to dość proste zadanie:

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

Komentarze

  • Musisz dodawać cudzysłowy wokół $1 lub ryzykujesz złamanie nazw plików zawierających spacje itp.
  • to nie ' t działa w przypadku takich rzeczy jak foo / .git / bar / baz Myślę, że możesz zrobić echo test.txt | awk -F ' / ' ' {print $ NF} ' | awk -F '.' ' {print $ NF} '

Odpowiedź

#!/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" 

Uruchom:

./script.sh index.html 

Wynik:

index html 

Więcej informacji: Rozszerzenie parametru powłoki | gnu.org

Odpowiedź

Aby to zrobić, należy wziąć pod uwagę kilka zastrzeżeń:

  • Plik foo.d/bar nie ma rozszerzenia, nie jest to plik foo z .d/bar rozszerzenie.
  • warto również wziąć pod uwagę, że .bashrc nie ma rozszerzenia.
  • Element . i .. powinny być prawdopodobnie traktowane specjalnie i traktowane jako nie mające żadnego rozszerzenia.
  • jakie jest rozszerzenie file.tar.gz? gz czy tar.gz? A co z holiday.picture.jpg lub bash-4.4?
  • Co należy zwrócić za foo.d/? Pusty lub d?

Tutaj chciałbym:

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

Komentarze

  • Doskonale radzi sobie z odpowiedziami, także zwykłymi zastrzeżeniami i przydatnym kodem, zwłaszcza jako funkcja.

Odpowiedź

I „dodam więcej opcji na wypadek, gdybyś miał zainstalowany sed lub 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 in sed i s/^.*?\.//&&print w perl: spróbuj podstawić najkrótszą sekwencję znaków, a nie ., po którym następuje znak . na początku ciągu; jeśli można było dokonać podstawienia, wydrukuj wynik podstawienia;
 % bash script.sh file.bin Extension: bin Extension: bin  

Odpowiedź

Uważaj. W Unix / Linux (i MacOS) „rozszerzenie nazwy pliku” ma tylko charakter informacyjny (jeśli aż tak dużo). Możesz doskonale mieć skrypt Perla o nazwie photo.gif lub plik GIF o nazwie poem.txt. Lub nawet plik o nazwie some.txt.png.

Komentarze

  • It ' jest tak samo pouczające w MS Windows, ' polega tylko na tym, że domyślny program powłoki przyjmuje silniejsze założenia dotyczące rozszerzenia – parowania zawartości i czy powinien istnieć niedopasowanie między nazewnictwem a treścią, całość zwykle zaczyna po prostu wykrzykiwać błędy, błahostka.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *