Jak uzyskać rozszerzenie pliku z bash? Oto, co próbowałem:
filename=`basename $filepath`
fileext=${filename##*.}
W ten sposób mogę uzyskać rozszerzenie bz2
ścieżki /dir/subdir/file.bz2
, ale mam problem ze ścieżką /dir/subdir/file-1.0.tar.bz2
.
Wolę rozwiązanie wykorzystujące tylko bash bez zewnętrznych programów, jeśli jest to możliwe.
Aby wyjaśnić moje pytanie, tworzyłem skrypt bash, aby wyodrębnić dowolne archiwum za pomocą jednego polecenia extract path_to_file
. Sposób wyodrębnienia pliku jest określany przez skrypt na podstawie jego typu kompresji lub archiwizacji, którym mogą być .tar.gz, .gz, .bz2 itp. Myślę, że powinno to obejmować manipulację ciągami, na przykład jeśli otrzymam rozszerzenie, .gz
to ja powinien sprawdzić, czy ma on .tar
wcześniej ciąg .gz
- jeśli tak, rozszerzenie powinno być .tar.gz
.
.tar.bz2
Odpowiedzi:
Jeśli nazwa pliku to
file-1.0.tar.bz2
, rozszerzenie tobz2
. Metoda używana do wyodrębnienia rozszerzenia (fileext=${filename##*.}
) jest całkowicie poprawna¹.Jak zdecydować, że chcesz być rozszerzenie
tar.bz2
, a niebz2
czy0.tar.bz2
? Najpierw musisz odpowiedzieć na to pytanie. Następnie możesz dowiedzieć się, które polecenie powłoki pasuje do Twojej specyfikacji.Jedną z możliwych specyfikacji jest to, że rozszerzenia muszą zaczynać się od litery. Ta heurystyka zawodzi w przypadku kilku popularnych rozszerzeń, takich jak
7z
, które można najlepiej traktować jako szczególny przypadek. Oto implementacja bash / ksh / zsh:Aby zapewnić przenośność POSIX, należy użyć
case
instrukcji do dopasowania wzorca.Inną możliwą specyfikacją jest to, że niektóre rozszerzenia oznaczają kodowanie i wskazują, że konieczne jest dalsze usuwanie. Oto implementacja bash / ksh / zsh (wymagająca
shopt -s extglob
w bash isetopt ksh_glob
w zsh):Zauważ, że
0
jest to rozszerzenie wfile-1.0.gz
.¹ i pokrewne konstrukcje są w POSIX , więc działają one w dowolnej nie-antycznej powłoce w stylu Bourne'a, takiej jak ash, bash, ksh lub zsh.
${VARIABLE##SUFFIX}
źródło
.
tokenem jest typem archiwum, na przykładtar
, czy jego typ0
niearchiwalny jak iteracja powinien się kończyć..patch.lzma
. Lepszym heurystyczny byłoby rozważyć ciąg po ostatnie.
: czy jest to przyrostek kompresji (.7z
,.bz2
,.gz
, ...), nadal rozbiórki.Możesz uprościć sprawy, po prostu dopasowując wzorce do nazwy pliku zamiast wyodrębnić rozszerzenie dwukrotnie:
źródło
Komentarze na ten temat tutaj: http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/
źródło
.tar.gz
rozszerzeniaOto moje ujęcie: Przetłumacz kropki na nowe linie, przeciągnij
tail
, uzyskaj ostatnią linię:źródło
Na przykład:
źródło
printf
jeśli nazwa pliku zawiera odwrotny ukośnik lub zaczyna się od-
:"${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
Pewnego dnia stworzyłem te trudne funkcje:
Znalazłem to proste podejście, bardzo przydatne w wielu przypadkach, nie tylko w przypadku rozszerzeń.
Do sprawdzania rozszerzeń - to proste i niezawodne
Do odcinania przedłużenia:
Aby zmienić rozszerzenie:
Lub jeśli lubisz "przydatne funkcje:
PS Jeśli podobały Ci się te funkcje lub okazały się przydatne, zapoznaj się z tym postem :) (i mam nadzieję, że skomentujesz).
źródło
Odpowiedź oparta na wielkości liter jest bardzo dobra i przenośna, ale jeśli chcesz tylko nazwę pliku i rozszerzenie w zmiennej, znalazłem to rozwiązanie:
Działa tylko z podwójnymi rozszerzeniami i pierwszym musi być „tar”.
Możesz jednak zmienić linię testową „tar” za pomocą testu długości łańcucha i powtórzyć poprawkę wiele razy.
źródło
rozwiązałem to za pomocą:
ale działa to tylko dla znanego typu archiwizacji, tylko w tym przypadku
tar
źródło