Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to write a function which returns a string which consists of two parts:

  1. option switch
  2. filename with spaces.

My problem is: How to quote in order to pass the result to another program?

#!/bin/bash
getOption() {
  echo "-C $1"
}
# prints first lines of man page of cp (copy) 
man $(getOption "$1") cp | head -10

In this sample I'm trying to pass a customized config file to man. Assuming the snippet above is named run.sh, the customized config is named my man.conf and both reside in the same directory I'm getting this error:

$ ./run.sh "my man.conf"
my: No such file or directory
Warning: cannot open configuration file my
# output from man for man…

As glenn jackman indicated: I was missing a point of Bash's docs

The root of the issue described above is that you need a way to maintain each argument as a separate word, even if that argument contains spaces. Quotes won't do it, but an array will.

So spaces are preserved when updating to

#!/bin/bash

args=("")
addOption() {
  args+=(-C "$1")
  return 0
}

$(addOption "$1")
man "${args[@]}" cp | head -10
share|improve this question
    
Your question is not clear... What is that cp in last line? – Sepahrad Salour Jul 15 '13 at 16:14
up vote 1 down vote accepted

see BashFAQ/050

Basically, you need to restructure. Even passing quotes back from the function won't work. This

getOption() {
  echo "-C '$1'"
}

will just lead to the error message cannot open configuration file 'my

Once you concatenate a string containing whitespace into another string, you cannot extract the added string as a single entity.

Given your question, you should simply do

man -C "$1" ...

But I suspect you want "run.sh" to be more complex than what you've shown. Please provide more details.

share|improve this answer
    
Yes, the intention of the function is to add option and its filename conditionally. The function's result can be part of the command in any case -- as it resolves to a valid option or empty string. And yes, your suggestion to use an array did the trick. – Stephan Jul 15 '13 at 17:15

You don't quote, you need to escape spaces on the command line, e.g.:

./run.sh my\ man.conf

In most shells, tab completion would help do this for you.

Of course, spaces in file and directory names are semi-evil, and the real fix is to try and avoid these.

p.s. I think your script has other issues besides just getting it the right arguments . . .

share|improve this answer
    
Spaces are not evil and need not be avoided. The real fix is to write programs that are not broken :) – slhck Jul 15 '13 at 16:30
    
@ernie thanks for your response. Unfortunately escaping doesn't make a difference: ./run.sh my\ man.conf = ./run.sh "my man.conf" I know the example is artificial but its short and -- I hope -- easy to reproduce. What other issues you find in the sample? – Stephan Jul 15 '13 at 16:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .