I’m fairly new to bash scripts, so this is probably a stupid syntax error, but why is this code not working?
for x in $(ls)
do
if [ -d $x ]
then
echo $x
fi
done
The separate for and if section work fine on their own, but this produces no output.
Two things. Never use
lsto iterate files, and quote parameter expansions"$x". The for and if syntax itself is correct. I prefer to put thedoandthenon the same line thoughFor 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 becauseforiterates words andlsoutputs 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[[.