From a shell script, how do I check if a directory contains files?
Something similar to this
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
but which works if the directory contains one or several files (the above one only works with exactly 0 or 1 files).
With some workaround I could find a simple way to find out whether there are files in a directory. This can extend with more with grep commands to check specifically .xml or .txt files etc. Ex :
ls /some/dir | grep xml | wc -l | grep -w "0"
Could you compare the output of this?
Some implementation notes:
for
loop avoids a call to an externalls
process. It still reads all the directory entries once. This can only be optimized away by writing a C program that uses readdir() explicitly.test -e
inside the loop catches the case of an empty directory, in which case the variable_ief
would be assigned the value "somedir/*". Only if that file exists will the function return "nonempty"test
implementation doesn't support the-e
flag.Small variation of Bruno's answer:
It works for me
ZSH
I know the question was marked for bash; but, just for reference, for zsh users:
Test for non-empty directory
To check if
foo
is non-empty:where, if
foo
is non-empty, the code in thefor
block will be executed.Test for empty directory
To check if
foo
is empty:where, if
foo
is empty, the code in thefor
block will be executed.Notes
We did not need to quote the directory
foo
above, but we can do so if we need to:We can also test more than one object, even if it is not a directory:
Anything that is not a directory will just be ignored.
Extras
Since we are globbing, we can use any glob (or brace expansion):
We can also examine objects that are placed in an array. With the directories as above, for example:
Thus, we can test objects that may already be set in an array parameter.
Note that the code in the
for
block is, obviously, executed on every directory in turn. If this is not desirable then you can simply populate an array parameter and then operate on that parameter:Explanation
For zsh users there is the
(F)
glob qualifier (seeman zshexpn
), which matches "full" (non-empty) directories:The qualifier
(F)
lists objects that match: is a directory AND is not empty. So,(^F)
matches: not a directory OR is empty. Thus,(^F)
alone would also list regular files, for example. Thus, as explained on thezshexp
man page, we also need the(/)
glob qualifier, which lists only directories:Thus, to check if a given directory is empty, you can therefore run:
and just to be sure that a non-empty directory would not be captured:
Oops! Since
Y
is not empty, zsh finds no matches for(/^F)
("directories that are empty") and thus spits out an error message saying that no matches for the glob were found. We therefore need to suppress these possible error messages with the(N)
glob qualifier:Thus, for non-empty directories we need the qualifier
(N/^F)
, which you can read as: "don't warn me about failures, directories that are not full".Similarly, for empty directories we need the qualifier
(NF)
, which we can likewise read as: "don't warn me about failures, full directories".