Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

2 Answers 2

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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.