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?

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 5 '17 at 17:52
  • @sphoenix, before any command using a glob whose expansion you want to use the nullglob rule. – Stéphane Chazelas Oct 5 '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 5 '17 at 17:56
  • @sphoenix, see edit. – Stéphane Chazelas Oct 5 '17 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.