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 foonão está vazio:
$ for i in foo(NF) ; do ... ; done
onde, se foonão estiver vazio, o código do forbloco será executado.
Teste para diretório vazio
Para verificar se fooestá vazio:
$ for i in foo(N/^F) ; do ... ; done
onde, se fooestiver vazio, o código do forbloco será executado.
Notas
Não precisamos citar o diretório fooacima, 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 forbloco é, 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 zshexppá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 Ynã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".