0

In the below function, I'm trying to print the file name if there are any files in the directory or an error if there's not, but the else part of the inner if/else block, which prints the error message, never runs.

It should be something logical but I can't figure it out.

walk_dir () {
    shopt -s nullglob dotglob

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then 
          printf "\nFiles under $(basename "$pathname")\n";
          printf "==========================================\n";

          walk_dir "$pathname";
        else 
          fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

          # Here is the problem
          if [ $fc -gt 0 ] && [ ! -z $fc ]; then 
            printf '%s\n' $(basename "$pathname");
          else 
            printf '\e[30mNo candidate file found.\e[39m\n';
          fi
        fi
    done
}
7
  • What condition you hope to cover in the else part that is not executed ? Commented Dec 6, 2019 at 8:44
  • @dash-o I'm trying to print an error if file count is zero or less Commented Dec 6, 2019 at 8:48
  • See details below. When you refer to file count is zero, do you refer to empty directories, or to special files ? Commented Dec 6, 2019 at 8:57
  • @dash-o Thank you for your answer and explanation, I refer to empty directories. Commented Dec 6, 2019 at 9:02
  • 1
    @tripleee Thanks, I edited the question and posted it in a new answer. Commented Dec 6, 2019 at 9:38

3 Answers 3

1

There are 3 cases for walk_dir

  • Non-empty folder
  • Empty folder
  • Regular file
  • Ignoring special file, probably N/A here.

When called for non-empty folder, walk_dir will make (recursive) on any sub folder (line #7), and then will print the base name of every regular file in line #12.

When called with empty folder, walk_dir will do nothing since "$1"/* expand to empty list.

When the directory contain files, the code will "count" the number of files in line #9. This l only process non-directories - probably files (assuming not special devices, etc). In this case it will make recursive call for each entry in the folder.

If there are regular files in the folder, the code will execute the find on line #8. On a regular file will always set fc="1", therefore the condition on line 11 will always be true, never getting into the else part on line #13.

     1  walk_dir () {
     2      shopt -s nullglob dotglob

     3      for pathname in "$1"/*; do
     4          if [ -d "$pathname" ]; then 
     5            printf "\nFiles under $(basename "$pathname")\n";
     6            printf "==========================================\n";

     7            walk_dir "$pathname";
     8          else 
     9            fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

    10            # Here is the problem
    11            if [ $fc -gt 0 ] && [ ! -z $fc ]; then 
    12              printf '%s\n' $(basename "$pathname");
    13            else 
    14              printf '\e[30mNo candidate file found.\e[39m\n';
    15            fi
    16          fi
    17      done
    18   }
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer. By the explanations, I think I should put the error message out of the for loop because it won't run if the directory is empty, right?
I believe you are right. There is no simple test for "empty" directory, given that a directory may contain "dot" files, and still looks empty.
0

According to @dash-o explanations I put the if condition before iterating over files and, it worked as I expected.

walk_dir () {
    shopt -s nullglob dotglob

    fc=$(find "$1" -maxdepth 1 -type f | wc -l);

    if [ $fc -eq 0 ] || [ -z $fc ]; then 
      printf '\e[30mNo candidate file found.\e[0m\n';  
    fi

    for pathname in "$1"/*; do
        if [ -d "$pathname" ]; then 
          printf "\nFiles under $(basename "$pathname")\n";
          printf "==========================================\n";

          walk_dir "$pathname";
        else 
          printf '%s\n' $(basename "$pathname");
        fi
    done
}

Comments

0

Too long for a comment!

I don't understand the usage of

fc=$(find "$pathname" -maxdepth 1 -type f | wc -l);

In that part of the code $pathname is either a file (not directory) or the search pattern of the for loop, if no file was found. So this code seems better:

if [[ -f $filename ]]
then
     # use input redirection to suppress filename
     fc=$(wc -l <"$filename")
else
     echo "not a plain file"
fi

1 Comment

Thanks. The purpose of that piece of code is to identify that it is an empty directory or not. I like your idea, but this code echoes the message on every iteration, either it's a search pattern or an empty directory. Maybe it's a result of a mistake in my implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.