ZSH
Eu sei que a pergunta foi marcada para bash; mas, apenas para referência, para usuários zsh :
Teste para diretório não vazio
Para verificar se foo
não está vazio:
$ for i in foo(NF) ; do ... ; done
onde, se foo
não estiver vazio, o código do for
bloco será executado.
Teste para diretório vazio
Para verificar se foo
está vazio:
$ for i in foo(N/^F) ; do ... ; done
onde, se foo
estiver vazio, o código do for
bloco será executado.
Notas
Não precisamos citar o diretório foo
acima, mas podemos fazer isso se precisarmos:
$ for i in 'some directory!'(NF) ; do ... ; done
Também podemos testar mais de um objeto, mesmo que não seja um diretório:
$ 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
Tudo o que não for um diretório será simplesmente ignorado.
Extras
Já que estamos globbing, podemos usar qualquer glob (ou expansão de chave):
$ 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
Também podemos examinar objetos colocados em uma matriz. Com os diretórios acima, por exemplo:
$ 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
Assim, podemos testar objetos que já podem estar configurados em um parâmetro de matriz.
Observe que o código no for
bloco é, obviamente, executado em cada diretório por vez. Se isso não for desejável, você pode simplesmente preencher um parâmetro de matriz e, em seguida, operar nesse parâmetro:
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
Explicação
Para usuários zsh, há o (F)
qualificador glob (consulte Recursos man zshexpn
), que corresponde a diretórios "completos" (não vazios):
$ 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/
O qualificador (F)
lista os objetos que correspondem: é um diretório E não está vazio. Portanto, (^F)
corresponde a: não é um diretório OU está vazio. Assim, (^F)
sozinho também listaria arquivos regulares, por exemplo. Portanto, conforme explicado na zshexp
página do manual, também precisamos do (/)
qualificador glob, que lista apenas os diretórios:
$ 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
Assim, para verificar se um determinado diretório está vazio, você pode executar:
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
e apenas para ter certeza de que um diretório não vazio não seria capturado:
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
Ops! Como Y
não está vazio, zsh não encontra correspondências para (/^F)
("diretórios que estão vazios") e, portanto, exibe uma mensagem de erro informando que nenhuma correspondência para o glob foi encontrada. Portanto, precisamos suprimir essas possíveis mensagens de erro com o (N)
qualificador glob:
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
Assim, para diretórios vazios, precisamos do qualificador (N/^F)
, que pode ser lido como: "não me avise sobre falhas, diretórios que não estão cheios".
Da mesma forma, para diretórios não vazios, precisamos do qualificador (NF)
, que também podemos ler como: "não me avise sobre falhas, diretórios completos".