Bash Script doesn't print out as expected. What is wrong with my script?

Solution 1:

First rule of debugging simple scripts:

If it doesn't work, try echoing.

In this case:

for i in $*; do
    echo  "testing if “{$i}” exists"
    if [ -d “{$i}” ]; then
        echo “${i} (Directory)”;
<... rest of the script ...>

You will immediately see that the reply is:

testing if “{Downloads}” exists
...

That is: the test is if ”{Downloads}” (smartquotes-accolade open-Downloads-accolade close smartquotes) exists.

That directory will probably not exist.

The smartquotes may be an oversight for a beginning shell-scripter. Bash (and most other shells as well) are very picky in the use of quotes. A single quote (') has a different meaning from a double-quote ("). Back-quotes mean something different as well. Smartquotes are the ones that mother gave you, don't do anything at all (if you forgive my Jefferson Airplane reference). You definitely want the double quotes (") here, because they allow variable expansion.

Next are the { and }.In your echo's, you give:

echo “${i} not found”

but in the if it is {$i}. Spot the difference. If you used

if [ -d "${i}" ]; then

it would have worked.

Kamil wrote in his comments:

You hardly ever want $*; you almost always want "$@" instead.

and he is right. There are complete pages devoted to the difference of $*and "$@", but the simplest way to show the difference is with:

#!/bin/bash
echo ------------------
echo '$*'
for i in $* ; do echo $i ; done
echo ------------------
echo '"$@"'
for i in "$@" ; do echo $i ; done
echo ------------------

(I called this script a) and execute with:

bash a 'plop 123' plop 123
------------------
$*
plop
123
plop
123
------------------
"$@"
plop 123
plop
123
------------------