dbmitch dbmitch - 4 months ago 9
Bash Question

Bash script - Piping command into another with escaped variables

Expanding on question answer by @chepner in

Bash script fails when running command with embedded quotes (source parameters)

Do I have to do anything special to with the $cmd variable if I want to pipe another command into it? Previously it has been split into args array to handle escaped quotes.

ie. Does the pipe symbol and adding an extra command also require special treatment?

I want to change the first line in this:

cmd=avconv
args=(-re -i /home/pi/test.mp3 -c:a libmp3lame -content_type audio/mpeg -b:a "$stream_bitrate" -legacy_icecast "$icecast_legacy")

stream_parameters=(-ice_name "$icecast_show" -f mp3)

icecast_setup="icecast://$icecast_user:$icecast_password@$icecast_server:$icecast_port$icecast_mount_url"

test_cmd="$start_cmd $stream_parameters $icecast_setup"
echo "Testing command: $cmd ${args} ${stream_parameters[@]} $icecast_setup"

# Run command
"$cmd" "${args[@]}" "${stream_parameters[@]}" "$icecast_setup"


To this:

cmd="arecord -f cd -D plughw:1,0 | avconv"


Will that still work on the last line? Or does the $cmd and $args have to be adjusted?

Also - what is the meaning of
[@]
in the last command - is that just expanding the array?

Answer

This will not work; the pipe will be treated as just another argument to the arecord command, not a pipe connecting record to avconv. At this point, you want to define a shell function:

my_cmd () {
    arecord -f cd -D plughw:1,0 | avconv "$@"
}

my_cmd "${args[@]}" "${stream_parameters[@]}" "$icecast_setup"

The arguments given to my_cmd are used as the arguments for avconv inside the function.

The [@] expands the array to each of its elements. @, specifically, has special meaning: each element is treated as a quoted word. For example,

$ a=("a  b" "c  d")
$ printf "%s\n" "${a[@]}"

prints two lines of output, a b and c d, since the array expansion produces two words. On the other hand,

$ printf "%s\n" "${a[*]}"

produces one line of output, a b c d, as the elements of the array are joined into one word, separated by a space. And

$ printf "%s\n" ${a[@]}

prints four lines of output, a, b, c, and d, since all whitespace in the expansion is used to split the expansion into individual words. (${a[*]} would have the same effect; the character used * or @ does not matter if the expansion is not quoted.)

Comments