ЗШ
Я знаю, що питання було позначене як баш; але, лише для довідки, для користувачів zsh :
Перевірка на непорожній каталог
Щоб перевірити, чи fooнемає порожнього:
$ for i in foo(NF) ; do ... ; done
де, якщо fooвін не порожній, код у forблоці буде виконуватися.
Перевірка порожнього каталогу
Щоб перевірити, чи fooпорожній:
$ for i in foo(N/^F) ; do ... ; done
де, якщо fooпорожній, forбуде виконаний код у блоці.
Примітки
Нам не потрібно було цитувати каталог fooвище, але ми можемо це зробити, якщо нам потрібно:
$ for i in 'some directory!'(NF) ; do ... ; done
Ми також можемо протестувати кілька об'єктів, навіть якщо це не каталог:
$ 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
Все, що не є каталогом, буде просто проігноровано.
Екстри
Оскільки ми є глобальними, ми можемо використовувати будь-який глобус (або розширення дужок):
$ 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
Ми також можемо вивчити об'єкти, які розміщені в масиві. Наприклад, із каталогами, як описано вище:
$ 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
Таким чином, ми можемо перевірити об'єкти, які вже можуть бути встановлені в параметрі масиву.
Зауважте, що код у forблоці, очевидно, виконується в кожному каталозі по черзі. Якщо це не бажано, ви можете просто заповнити параметр масиву і потім працювати над цим параметром:
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
Пояснення
Для користувачів zsh існує (F)глобальний класифікатор (див. man zshexpn), Який відповідає "повному" (не порожньому) каталогу:
$ 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/
Класифікатор (F)перераховує об'єкти, які відповідають: це каталог І не порожній. Отже, (^F)відповідає: не каталог АБО порожній. Таким чином, (^F)поодинці були б також перелічені звичайні файли, наприклад. Таким чином, як пояснено на сторінці zshexpman, нам також потрібен (/)глобальний класифікатор, який містить лише каталоги:
$ 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
Таким чином, щоб перевірити, чи вказаний каталог порожній, ви можете запустити:
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
і просто переконатися, що не порожній каталог не буде захоплений:
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
На жаль! Оскільки Yне порожньо, zsh не знаходить відповідності для (/^F)("каталоги, які порожні"), і, таким чином, висилає повідомлення про помилку, вказуючи, що не було знайдено відповідностей для глобального. Тому нам потрібно придушити ці можливі повідомлення про помилки за допомогою (N)глобального класифікатора:
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
Таким чином, для порожніх каталогів нам потрібен класифікатор (N/^F), який ви можете прочитати так: "не попереджайте мене про збої, каталоги, які не заповнені".
Аналогічно, для непорожніх каталогів нам потрібен кваліфікатор (NF), який ми можемо також прочитати так: "Не попереджайте мене про збої, повні каталоги".