This command
find . -name . -o -type d -print -prune
will generate non-empty output iff there is at least one directory in the current working directory (the core idea came from this answer). You can include it in your shell code as a test. Something like
if ( cd -- "$dir" && [ -z "$(find . -name . -o -type d -print -prune)" ] ); then
…
fi
where the subshell ( ) prevents cd from changing the current working directory of the main script. You could use find "$dir" … without cd but what if $dir expands to something starting with -? Double dash works with cd, not with find. Well, your main find (the one in <()) starts in ., so one may think all pathnames generated by it will start with .. It seems not all implementations of find behave like this though, so it's still good to code defensively.
Alternatively you can build the test into the main find command (inside <()):
find . -type d -exec sh -c '
cd -- "$1" && [ -z "$(find . -name . -o -type d -print -prune)" ]
' find-sh {} \; -print
find-sh is explained here: What is the second sh in sh -c 'some shell code' sh?
Note this approach will run one additional sh per directory (with or without subdirectories), this is sub-optimal. I'm introducing it as a small step towards a bigger improvement, because piping to read is not the best way (if you must then it's good you use -r; but consider IFS= as well).
When piping find to read like you did, names containing newlines will make the code fail. A good practice is to run everything from within find, if possible. In your case it seems possible. The following code is standalone (not inside <()).
find . -type d -exec sh -c '
cd -- "$1" && [ -z "$(find . -name . -o -type d -print -prune)" ] && do_something_more_with "$1"
' find-sh {} \;
The above still runs one sh per directory. Now it can be improved by:
find . -type d -exec sh -c '
for dir do
( cd -- "$dir" && [ -z "$(find . -name . -o -type d -print -prune)" ] ) && do_something_more_with "$dir"
done
' find-sh {} +
Here I used … && do_something_more_with "$dir" but you can choose if … then … instead.
In your case do_something_more_with "$dir" will be
{ echo "$dir"; /Users/rusl/.cliapps/MQA_identifier "$dir" | tee "$dir"/mqa.log; }
where { } group commands so the preceding && makes the entire group run conditionally.
Maybe instead of do_something_more_with "$dir" it's better to do_something_more_with . in the $dir directory. The relevant line will be:
( cd -- "$dir" && [ -z "$(find . -name . -o -type d -print -prune)" ] && do_something_more_with . )
But it's your decision. You can still echo "$dir" (or better printf "%s\n" "$dir"; note the entire shell code run by find -exec is single-quoted, so don't type printf '%s\n').
In case there are extremely many subdirectories in some directory, we really don't need the inner find to list them all. To tell whether the output is empty or not it's enough to break after the first line:
[ -z "$(find . -name . -o -type d -print -prune | head -n 1)" ]
(With head -c 1 we could break after the first character, but I think head -c is not portable.)
So the optimized code may look like this:
find . -type d -exec sh -c '
for dir do
( cd -- "$dir" && [ -z "$(find . -name . -o -type d -print -prune | head -n 1)" ] ) \
&& { printf "%s\n" "$dir"; /Users/rusl/.cliapps/MQA_identifier "$dir" | tee "$dir"/mqa.log; }
done
' find-sh {} +
also I think this script processes every subdirectory as many times as it is nested inside the parent top most directory. Not that it is critical, but still not efficient.
Unable to reproduce. find . -type d prints every directory just once. Maybe MQA_identifier works recursively. If it does then it (but not strictly the script) will process subdirectories multiple times (with tee writing to a file on a different level in the directory tree each time).