Nesting if in a for loop

Two things. Never use ls to iterate files, and quote parameter expansions "$x". The for and if syntax itself is correct. I prefer to put the do and then on the same line though

for file in *; do
    if [[ -d "$file" ]]; then
        echo "$file is a directory"
    elif [[ -f "$file" ]]; then
        echo "$file is a regular file"
    fi
done

For learning bash, I recommend reading http://mywiki.wooledge.org/BashGuide most other tutorials and guides are unfortunately not very good.

The reason for not doing for x in $(ls) to iterate files is because for iterates words and ls outputs lines with filenames. if those filenames happen to contain whitespace, those filenames will be split up further into words, so you'll be iterating the words of the filenames, not the filenames. Obviously, for the simple cases that works, but why use a half-working solution when there's a shorter and more elegant way that handles all cases?

With for x in * the shell replaces the * with all filenames matching that pattern in the current directory (called pathname expansion), and each filename will be a separate word so it will work no matter what characters the filename contains. Filenames can contain any character (including newlines), except / and the NUL byte (\0).

See http://mywiki.wooledge.org/ParsingLs for more on that.

As for using [[ vs [. [ is a command inherited from the bourne shell, used to test strings, files and numbers. Bash has added a more powerful [[ keyword that can do everything [ can and more. If you're writing an sh script, you must use [, but in bash scripts you should use the more powerful [[ and (( syntaxes. See http://mywiki.wooledge.org/BashFAQ/031 for more about the difference between [ and [[.


Maybe there's a problem with the characters being used to separate the different parts of the statement?

What if you tried:

for x in $(ls); do if [ -d $x ]; then echo $x; fi; done

Does that produce output?


1) the syntax is perfectly legal

2) Yes, you can nest "if/else" blocks inside a loop. You can also nest inner loops within an outer loop :)

3) "if [ -d $x ]" checks if "x" is a "directory".

If you don't see any output, then perhaps you don't have any subdirectories?

SUGGESTION:

  • open a terminal window

  • Run your script. See whether or not you get any output.

  • If not, then type mkdir moose. This will create a subdirectory called (uncoincidentally) "moose".

  • Re-run your script. You should see at least "moose".