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
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ź
$ 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 przypadkutest.txt
. -
wyjście standardowego wyjścia
echo
jest przesyłane potokiem do standardowego wejścia dlaawk
, które dzieli ciąg (test.txt
) na.
, a następnie drukuje ostatni element podziału (w tym przypadkutxt
).
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 plikfoo
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
czytar.gz
? A co zholiday.picture.jpg
lubbash-4.4
? - Co należy zwrócić za
foo.d/
? Pusty lubd
?
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
insed
is/^.*?\.//&&print
wperl
: 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.
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.