Skip to main content
OpenNomad's little corner of the web

The many circles of quoting hell

When it comes to shell programming quotes and escaped quotes and escaped escapes seem to offer a limitless pit of fun. At times it seems nearly insurmountable and depending on whether you are running interactively or from a script.

Recently I had the opportunity to assist in some bash shell scripting. The issue was largely based on trying to get smbclient to run via some options that were being passed and parsed into a script.

The fun thing was that the command, as it was built in the script, would run perfectly when cut and pasted intoa terminal, but within the script it would generate an error, that seemed to point to some quoting issues.

After much trial and error I remembered having seen something similar in the past, where I was trying to build a complex command line which also required nested double and single quotes as well as pound signs.

In essence I build the command as follows (stupid things ignored):

LS_OPTIONS="-ltr" COMMAND="ls" COMMAND="$COMMAND $LS_OPTIONS" FILE_NAME="a long file with spaces in them" COMMAND="$COMMAND "$FILE_NAME"" PIPE_COMMAND_1="cut -f 7 -d ' '" PIPE_COMMAND_2="sed -e 's/^/"/g; s/$/"/g'" COMMAND="$COMMAND | $PIPE_COMMAND_1 | $PIPE_COMMAND_2" echo $COMMAND $COMMAND This will fail with: ls -ltr "a long file with spaces in them" | cut -f 7 -d ' ' | sed -e 's/^/"/g; s/$/"/g' ls: invalid option -- e Try `ls --help' for more information. If you try and cut and paste the echoed command it succeeds, just not within the script.

However if $COMMAND is echoed to a new shell as follows, it works (only the last line changes): LS_OPTIONS="-ltr" COMMAND="ls" COMMAND="$COMMAND $LS_OPTIONS" FILE_NAME="a long file with spaces in them" COMMAND="$COMMAND "$FILE_NAME"" PIPE_COMMAND_1="cut -f 7 -d ' '" PIPE_COMMAND_2="sed -e 's/^/"/g; s/$/"/g'" COMMAND="$COMMAND | $PIPE_COMMAND_1 | $PIPE_COMMAND_2" echo $COMMAND echo $COMMAND | sh and you will see: ls -ltr "a long file with spaces in them" | cut -f 7 -d ' ' | sed -e 's/^/"/g; s/$/"/g' "09:45" I did spend some time trying to figure out why this works, but came up inconclusive. In the meantime, I've used this trick a few times now.

Hope this helps someone else get out of the shell pit.

\\@matthias

posts