ЗШ
Я знаю, что вопрос был помечен как bash; но, для справки, для пользователей 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)
квалификатор glob (см. 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)
одиночку также будут перечислены, например, обычные файлы. Таким образом, как объясняется на zshexp
странице руководства , нам также нужен (/)
квалификатор glob, который перечисляет только каталоги:
$ 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)
квалификатора glob:
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
Таким образом, для пустых каталогов нам нужен квалификатор (N/^F)
, который можно читать как «не предупреждать меня о сбоях, каталогах, которые не заполнены».
Точно так же для непустых каталогов нам нужен квалификатор (NF)
, который мы можем также читать как: «не предупреждать меня о сбоях, полные каталоги».