[ -f /*.txt ]
zwróciłoby wartość prawdy tylko wtedy, gdy istnieje jeden (i tylko jeden) plik, /
którego nazwa się nie kończy, .txt
i jeśli jest to zwykły plik lub dowiązanie symboliczne do zwykłego pliku.
Jest tak, ponieważ symbole wieloznaczne są rozszerzane przez powłokę przed przekazaniem do polecenia (tutaj [
).
Więc jeśli istnieje /a.txt
i /b.txt
, [
zostanie przekazany 5 argumentów: [
, -f
, /a.txt
, /b.txt
i ]
. [
skarżyłby się wtedy na -f
zbyt wiele argumentów.
Jeśli chcesz sprawdzić, czy *.txt
wzorzec rozwija się do co najmniej jednego nie ukrytego pliku (zwykłego lub nie):
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
jest bash
specyficzny, ale muszle podoba ksh93
, zsh
, yash
, tcsh
mają te same oświadczenia.
Zauważ, że znajduje te pliki, czytając zawartość katalogu, wcale nie próbuje uzyskać dostępu do tych plików, co czyni go bardziej wydajnym niż rozwiązania, które wywołują polecenia takie jak ls
lub stat
na tej liście plików obliczonych przez powłokę.
Standardowy sh
odpowiednik to:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "$@"
esac
Problem polega na tym, że w przypadku powłok Bourne lub POSIX, jeśli wzorzec nie pasuje, rozwija się do siebie. Jeśli więc zostanie *.txt
rozwinięty *.txt
, nie wiesz, czy to dlatego, że nie ma .txt
pliku w katalogu, czy dlatego, że istnieje jeden plik o nazwie *.txt
. Korzystanie [*].txt *.txt
pozwala na rozróżnienie między nimi.
/
? Ponadto brakuje Ci wcześniej średnikafi
.