Checking from shell script if a directory contains files
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).
Solution 1:
Three best tricks
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
This trick is 100% bash
and invokes (spawns) a sub-shell. The idea is from Bruno De Fraine and improved by teambob's comment.
files=$(shopt -s nullglob dotglob; echo your/dir/*)
if (( ${#files} ))
then
echo "contains files"
else
echo "empty (or does not exist or is a file)"
fi
Note: no difference between an empty directory and a non-existing one (and even when the provided path is a file).
There is a similar alternative and more details (and more examples) on the 'official' FAQ for #bash IRC channel:
if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
then
echo "contains files"
else
echo "empty (or does not exist, or is a file)"
fi
[ -n "$(ls -A your/dir)" ]
This trick is inspired from nixCraft's article posted in 2007. Add 2>/dev/null
to suppress the output error "No such file or directory"
.
See also Andrew Taylor's answer (2008) and gr8can8dian's answer (2011).
if [ -n "$(ls -A your/dir 2>/dev/null)" ]
then
echo "contains files (or is a file)"
else
echo "empty (or does not exist)"
fi
or the one-line bashism version:
[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"
Note: ls
returns $?=2
when the directory does not exist. But no difference between a file and an empty directory.
[ -n "$(find your/dir -prune -empty)" ]
This last trick is inspired from gravstar's answer where -maxdepth 0
is replaced by -prune
and improved by phils's comment.
if [ -n "$(find your/dir -prune -empty 2>/dev/null)" ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
a variation using -type d
:
if [ -n "$(find your/dir -prune -empty -type d 2>/dev/null)" ]
then
echo "empty directory"
else
echo "contains files (or does not exist or is not a directory)"
fi
Explanation:
-
find -prune
is similar thanfind -maxdepth 0
using less characters -
find -empty
prints the empty directories and files -
find -type d
prints directories only
Note: You could also replace [ -n "$(find your/dir -prune -empty)" ]
by just the shorten version below:
if [ `find your/dir -prune -empty 2>/dev/null` ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
This last code works most of the cases but be aware that malicious paths could express a command...
Solution 2:
The solutions so far use ls
. Here's an all bash solution:
#!/bin/bash
shopt -s nullglob dotglob # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
Solution 3:
How about the following:
if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
This way there is no need for generating a complete listing of the contents of the directory. The read
is both to discard the output and make the expression evaluate to true only when something is read (i.e. /some/dir/
is found empty by find
).
Solution 4:
Try:
if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi