ZSH
Wiem, że pytanie było przeznaczone do basha; ale tylko w celach informacyjnych dla użytkowników zsh :
Sprawdź, czy katalog nie jest pusty
Aby sprawdzić, czy foo
jest niepusty:
$ for i in foo(NF) ; do ... ; done
gdzie, jeśli foo
nie jest pusta, kod w for
bloku zostanie wykonany.
Sprawdź, czy katalog jest pusty
Aby sprawdzić, czy foo
jest pusty:
$ for i in foo(N/^F) ; do ... ; done
gdzie, jeśli foo
jest puste, kod w for
bloku zostanie wykonany.
Uwagi
Nie foo
musieliśmy cytować powyższego katalogu , ale możemy to zrobić, jeśli zajdzie taka potrzeba:
$ for i in 'some directory!'(NF) ; do ... ; done
Możemy również przetestować więcej niż jeden obiekt, nawet jeśli nie jest to katalog:
$ mkdir X # empty directory
$ touch f # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done # echo empty directories
X
Wszystko, co nie jest katalogiem, zostanie po prostu zignorowane.
Dodatki
Ponieważ globujemy, możemy użyć dowolnego globu (lub rozwinięcia nawiasów):
$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf # create regular file
$ touch X1/f # directory X1 is not empty
$ touch Y1/.f # directory Y1 is not empty
$ ls -F # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo # print empty directories
X X2 Y Y2
Możemy również zbadać obiekty umieszczone w tablicy. Z katalogami jak wyżej, na przykład:
$ ls -F # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*) # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z
W ten sposób możemy testować obiekty, które mogą już być ustawione w parametrze tablicy.
Zauważ, że kod w for
bloku jest oczywiście wykonywany po kolei w każdym katalogu. Jeśli nie jest to pożądane, możesz po prostu wypełnić parametr tablicy, a następnie operować na tym parametrze:
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
Wyjaśnienie
Dla użytkowników zsh istnieje (F)
kwalifikator glob (zobacz man zshexpn
), który dopasowuje „pełne” (niepuste) katalogi:
$ mkdir X Y
$ touch Y/.f # Y is now not empty
$ touch f # create a regular file
$ ls -dF * # list everything in the current directory
f X/ Y/
$ ls -dF *(F) # will list only "full" directories
Y/
Kwalifikator (F)
wyświetla listę zgodnych obiektów: jest katalogiem ORAZ nie jest pusty. Tak więc (^F)
pasuje: nie jest katalogiem LUB jest puste. W związku z tym (^F)
, na przykład , sam wyświetlałby również zwykłe pliki. Tak więc, jak wyjaśniono na zshexp
stronie podręcznika , potrzebujemy również (/)
kwalifikatora glob, który zawiera tylko katalogi:
$ mkdir X Y Z
$ touch X/f Y/.f # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z
Dlatego, aby sprawdzić, czy dany katalog jest pusty, możesz uruchomić:
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
i tylko po to, aby mieć pewność, że niepusty katalog nie zostanie przechwycony:
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
Ups! Ponieważ Y
nie jest puste, zsh nie znajduje żadnych dopasowań dla (/^F)
(„katalogi, które są puste”) i dlatego wypluwa komunikat o błędzie informujący, że nie znaleziono żadnych dopasowań dla globu. Dlatego musimy pomijać te możliwe komunikaty o błędach za pomocą (N)
kwalifikatora glob:
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
Dlatego dla pustych katalogów potrzebujemy kwalifikatora (N/^F)
, który można odczytać jako: „nie ostrzegaj mnie o awariach, katalogach, które nie są pełne”.
Podobnie, dla niepustych katalogów potrzebujemy kwalifikatora (NF)
, który możemy również odczytać jako: "nie ostrzegaj mnie o awariach, pełne katalogi".