Passing shell variables containing spaces as argum

2019-08-04 15:53发布

问题:

I know there are many of these questions out there already, but my situation is unique enough that none of them have helped me thus far.

I'm writing a script that will reformat my (poorly tagged) music library. It's currently in the form of Music/Genre/Artist/Album/##-Title.wav.

From the Music directory, I run my script1, which calls find -name "*.wav" -exec script2 {} ${other_args}. Script2 parses the path to variables, creates the appropriate output directory if it doesn't exist, and then calls ffmpeg to do the compression.

ex: ($sourcefilepath contains {} from find)

ffmpeg -i "$sourcefilepath" "$path/$to/$outfile.$extension"

If my file name or path contains no spaces, it works like a charm.

If it contains spaces, ffmpeg fails, with the following error:

Blues/Country Blues/Rhythm, Country And Blues/08-Natalie Cole & Reba McEntire Since I Fell For You.wav: No such file or directory

Note: that's the source file it can't find. The output file appears to be working correctly, even with spaces. That's not the full command I'm running (it has some -metadata flags too, but that also appears to be working correctly. I'm debugging with the command I wrote above).

The interesting thing here is that ffmpeg is NOT interpreting $sourcefilepath as two args, it just can't find the file I specified. Running the following from the Music directory works.

ffmpeg -i Blues/Country\ Blues/Rhythm\,\ Country\ And\ Blues/08-Natalie\ Cole\ \&\ Reba\ McEntire\ \ \ Since\ I\ Fell\ For\ You.wav output.flac

I'm kind of stuck here. The other information on the web involves getting a command to see a variable with a space as one arg instead of multiple. I appear to have done that, but ffmpeg can't find my file now.

Normally I'd just use find -name "*.wav" -exec ffmpeg -i {} ${args} \; but I need to process the file path to extract my metadata.

I'm fairly new to shell scripting; does anybody know what's going on here?

回答1:

My psychic powers suggest that at some point in your code, you're doing something along the lines of:

something=$(echo $filename | something)

This should instead have been:

something=$(echo "$filename" | something)

Here's a script demonstrating why this is a problem:

#!/bin/sh
filename="Reba McEntire   Since I fell"    
echo "$filename"    # Correct, quoted
echo $filename      # Incorrect, unquoted

It outputs:

Reba McEntire   Since I fell
Reba McEntire Since I fell

You'll notice that

  • the first line has three spaces after the artist, as in your correct command.
  • the second line has one space after the artist, as in your error message.

This is due to unquoted variable expansion undergoing wordsplitting. echo then concatenates the arguments with single spaces. The net result is multiple whitespace coalescing into one space.



标签: shell ffmpeg