Home > OS >  Different errors in $() command substitution
Different errors in $() command substitution

Time:11-19

I'm getting different errors running the code below (it counts the number of .mp3 files in each user directory):

    for us in /home/*
    do
            if [ -d $us ]
            then
                    LT=$(find $us -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3")
    
                    N_MP3=$("$LT" | grep "\.mp3$" | wc -l)
                    N_MP3=$($LT | grep "\.mp3$" | wc -l)
                    N_MP3=$(find $us -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3" | grep "\.mp3$" | wc -l)
            fi
    done

Considerer that we have, in some user directory, let's say user=ubuntu, the files:

  • sample.jpg
  • sample.mp3

So let's run the code:


(1) Doing "$LT" | ..., I get the message:

/home/ubuntu/Desktop/Songs/sample.mp3 /home/ubuntu/Desktop/Images/sample.jpg: No such file or directory

which means "$LT" command was executed and found all .mp4, .mp3 or .jpg files in my user and then gives that error.


(2) Doing $LT | ..., which is equivalent to $(find $us -name ".jpg" -o -name ".mp4" -o -name "*.mp3") | ... I get the message /home/ubuntu/Desktop/Songs/sample.mp3: Permission denied. It means $LT command was executed and found only .mp3 file and then gives that error.

If I delete sample.jpg from my user=ubuntu, then in both cases I got the same error message: /home/ubuntu/Desktop/Songs/sample.mp3: Permission denied.

I know (but don't know why) I should use an echo command before $LT, but I'd like to know what's happening in theses cases which I didn't use echo before. Please, can someone shed a light on these errors?

CodePudding user response:

LT=$( ...)

You're using command substitution, so you're not storing a string for later reuse, you're trying to execute the output of the find command; that's not going to work.

Slightly more elegant:

function lt() { find $1 -name "*.jpg" -o -name "*.mp4" -o -name "*.mp3"; }
for us in /home/*
do
   if [ -d "$us" ]; then
        N_MP3=$(lt "$us" | grep "\.mp3$" | wc -l)
   fi
done

CodePudding user response:

This happens due to word splitting.

When you word split, the first word will become the command name, and remaining words will become arguments.

When you don't word split, the entire value will be used as the command name.

Bash shows the command name you tried to execute when it's not found, which is why the values are reflected in the error message:

$ var="foo bar baz"

$ foo bar baz
-bash: foo: command not found
$ $var
-bash: foo: command not found

$ "foo bar baz"
-bash: foo bar baz: command not found
$ "$var"
-bash: foo bar baz: command not found
  • Related