Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shell variable with spaces , quoting for single command line option

Autoconf scripts have trouble with a filename or pathname with spaces. For example,

./configure CPPFLAGS="-I\"/path with space\""

results in (config.log):

configure:3012: gcc  -I"/path with space"  conftest.c  >&5
gcc: with: No such file or directory
gcc: space": No such file or directory

The compile command from ./configure is ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' and I am not able to modify this (I could perhaps, but working around autoconf in this way is not a general solution).

I think it comes down to getting a shell variable that contains spaces to be parsed as a single command line variable rather than split at spaces. The simplest shell example I can come up with is to create a file with spaces and attempt to list is with ls with a shell variable as the argument to ls:

$ touch "a b"
$ file="a b"
$ ls $file
ls: a: No such file or directory
ls: b: No such file or directory

This works, but is illegal since in autoconf I can't modify the shell code:

$ ls "$file"
a b

None of the following attempts at quoting things work:

$ file="\"a \"b"; ls $file
ls: "a: No such file or directory
ls: b": No such file or directory
$ file="a\ b"
$ file="a\\ b"
$ file="`echo \\"a b\\"`"

and so on.

Is this impossible to accomplish in shell scripts? Is there a magical quoting that will expand a shell variable with spaces into a single command line argument?

like image 319
Patrick Avatar asked Nov 12 '09 17:11

Patrick


People also ask

How do you pass variables in single quotes?

If the backslash ( \ ) is used before the single quote then the value of the variable will be printed with single quote.

How do you pass arguments with spaces to a shell script?

You should just quote the second argument. Show activity on this post. If calling from any Unix shell, and the parameter has spaces, then you need to quote it. You should also quote every variable used within the function/script.

Can you use single quotes in bash?

3.1. 2.2 Single QuotesEnclosing characters in single quotes (' ' ') preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.


2 Answers

You should try to set the $IFS environment variable.

from man bash(1):

IFS - The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ''space tab newline''.

For example

IFS=<C-v C-m>  # newline
file="a b"
touch $file
ls $file

Don't forget to set $IFS back or strange things will happen.

like image 110
Chen Levy Avatar answered Oct 22 '22 20:10

Chen Levy


if you give command

 gcc -I"x y z"

in a shell then certainly the single command line parameter "-Ix y z" will be passed to gcc. There is no question to that. That's the whole meaning of double quotes: things inside double quotes are NOT subject to field splitting, and so not subject to $IFS either, for instance.

But you need to be careful about the number of quotes you need. For instance, if you say

 file="a b" # 1

and then you say

 ls $file # 2

what happens is that the file variable's contents are 'a b', not '"a b"', because the double quotes were "eaten" when line 1 was parsed. The replaced value is then field-separated and you get ls on two files 'a' and 'b'. The correct way to get what you want is

 file="a b"; ls "$file"

Now the problem in your original case is that when you set a variable to a string that CONTAINS double quotes, the double quotes are later not interpreted as shell quote symbols but just as normal letters. Which is why when you do something like

 file="\"a b\""; ls $file

actually the shell tokenizes the contents of the file variable into '"a' and 'b"' when the ls command is analyzed; the double quote is no longer a shell quote character but just part of the variable's contents. It's analogous to that if you set

 file="\$HOME"; ls $file

you get an error that '$HOME' directory does not exist---no environment variable lookup takes place.

So your best options are

  1. Hack autoconf
  2. Do not use path names with spaces (best solution)
like image 33
Antti Huima Avatar answered Oct 22 '22 19:10

Antti Huima