7

I was trying to write a shell script that will take a directory path d as an argument and recursively print a depth indented list of all files and directories in d. However, the argument d is optional and if no argument is given, a depth indented list of all files and directories​ ​in​ ​the​ ​current​ ​ directory​ will​ ​be printed. Here is my code:

# the method for tree

myspace="" spaceCount=0 tree(){
cd "$1" for i in *; do if [ -d "$i" ]; then echo -n "|"
for (( j=0;j<spaceCount;j++ )) do echo -n "$myspace"
done echo "--$i" spaceCount=$((spaceCount+1)) myspace=" |" tree "$i" else echo -n "|" for (( j=0;j<spaceCount;j++ )) do echo -n "$myspace"
done echo "--$i" fi done cd ../ spaceCount=$((spaceCount-1)) }

if [ "$1" != "" ]; then file="$1" fi echo ".$file" tree "$file"

But when a folder is empty, it's printing a star like this:enter image description here

How can I solve the problem?

sphoenix
  • 173
  • 4

1 Answers1

11

In bash and Bourne-like shells in general (zsh being the exception), globs like * that match no file expand to themselves (your script uses ksh93 syntax, also recognised by bash and zsh, though in zsh you'd get fatal errors by default for non-matching globs).

echo * in a directory that contains no file (or only hidden files) outputs *.

Here instead of for i in *, use for i in *(N) (zsh) or for i in ~(N)* (ksh93) or if using bash, set the nullglob option (with shopt -s nullglob) so that the globs that don't match expand do nothing.

Alternatively, you could add a [ -e "$i" ] || continue at the start or your for loop to filter out the * by checking for file existence (would affect the behaviour for directories you have read but not search permissions to though¹).

More reading at Why is nullglob not default?


¹ In those directories, * would expand to all the non-hidden files, but [ -e "$i" ] would return false for everyone of them as the stat() system call would return with permission denied

  • Where should I add shopt -s nullglob? – sphoenix Oct 05 '17 at 17:52
  • @sphoenix, before any command using a glob whose expansion you want to use the nullglob rule. – Stéphane Chazelas Oct 05 '17 at 17:54
  • Alternatively, you could add a [ -e "$i" ] || continue at the start or your for loop to filter out the * by checking for file existence (would affect the behaviour for directories you have read but not search permissions to though). Could you kindly elaborate on "would affect the behaviour for directories you have read but not search permissions to though", please? – sphoenix Oct 05 '17 at 17:56
  • @sphoenix, see edit. – Stéphane Chazelas Oct 05 '17 at 18:16