I'm writing a shell script in which I need to loop over directories and then loop over files inside them. So I've written this function:
loopdirfiles() {
#loop over dirs
for dir in "${PATH}"/*
do
for file in "${dir}"/*
do
echo $file
done
done
}
The problem is that it echoes something like path/to/dir/*
on empty directories.
Is there a way to use this approach and ignore those kind of directories?
You can cut the *
from the directory name instead of completely ignoring it:
[[ $file == *"*" ]] && file="${file/%\*/}"
#this goes inside the second loop
Or if you want to ignore the empty directory:
[[ -d $dir && $ls -A $dir) ]] || continue
#this goes inside the first loop
Another way:
files=$(shopt -s nullglob dotglob; echo "$dir"/*)
(( ${#files} )) || continue
#this goes inside the first loop
Or you can turn on the nullglob
(mentioned by Etan Reisner) and dotglob
altogether:
shopt -s nullglob dotglob
#This goes before first loop.
nullglob
If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves.
dotglob
If set, Bash includes filenames beginning with a ‘.’ in the results of filename expansion.
Note: dotglob
includes hidden files (files with a .
at the beginning in their names)