Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. 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

Assuming I want to run commnand stored inside the variable with nullglob turned on. For example:

shopt -s nullglob
a="echo [foo]bar"
${a}

This gives me an empty output due to the nullglob option of course, but I want the following output (which I am not able to get):

[foo]bar

I tried escaping [] with \ but that just gives me:

\[foo\]bar

What is the correct way of escaping it?

EDIT (clarification with some context):

I have a script like this:

shopt -s nullglob
for file in tmp/*.pdb; do
    base="$(basename ${file} .pdb)"
    a="command --option [${base}]foo"
    ${a}
done
shopt -u nullglob

What I wanted to achieve is to run command for each file with an option which has [] as ordinary characters (without any matching). The nullglob here was used just for the for loop.

That is if "tmp" contains "a.pdb" run:

command --option '[a]foo'

and nothing if no such file is present.

In a meantime I figured out that moving "shopt -u nullglob" as the first command in the for loop seems to solve the problem. However, I am curious if I can somehow escape the [] even with nullglob.

share|improve this question
    
Sorry, my bad. I'd misunderstood. Could you clarify what output you expect if i) there is a file matching [foo]bar and ii) if there isn't? – terdon Sep 17 '15 at 14:51
    
Also, you seem to be attempting to recreate the behavior of the shell without nullglob. Why not just unset nullglob? What am I missing? – terdon Sep 17 '15 at 14:59
    
@terdon I guess the original question wasn't clear at all, sorry. :-) I added some clarification. – krab1k Sep 17 '15 at 15:25
    
Ah, yes, that makes more sense :) See updated answer, does that help? – terdon Sep 17 '15 at 15:39
up vote 3 down vote accepted

First, read I'm trying to put a command in a variable, but the complex cases always fail!.

Then, define a function:

a () {
    echo "[foo]bar"
}

For your script, there is no reason to put the command in a variable first anway; just run the command.

shopt -s nullglob
for file in tmp/*.pdb; do
    base="$(basename ${file} .pdb)"
    command --option "[${base}]foo"
done
shopt -u nullglob

If you must store something in variables, separate the command from its options, and use an array to hold the options.

shopt -s nullglob
cmd=command
for file in tmp/*.pdb; do
    base="$(basename ${file} .pdb)"
    options=( --option "[${base}]foo" )
    "$cmd" "${options[@]}"
done
shopt -u nullglob
share|improve this answer
    
The purpose of having all of this in a variable was to write it to the log if command fails. However, since command is the always the same, logging the options is sufficient (which I didn't realize earlier) and the array approach you mentioned works great. Thanks! – krab1k Sep 18 '15 at 5:19

I don't understand why you're saving the command as a variable. Why not do something like what I show below and avoid the problem?

shopt -s nullglob
for file in tmp/*.pdb; do
    base="$(basename ${file} .pdb)"
    command --option "[${base}]foo"
done
shopt -u nullglob

Alternatively, if you need the command in a variable for other reasons, you could remove the nullglob and just make sure that files exist before running the command:

for file in tmp/*.pdb; do
  if [ -e "$file" ]; then
        base="$(basename ${file} .pdb)"
        a="command --option [${base}]foo"
        ${a}
done

It's rarely a good idea to save commands as variables. Another approach would be to save the options as variables instead:

shopt -s nullglob
for file in tmp/*.pdb; do
    base="$(basename ${file} .pdb)"
    a="--option [${base}]foo"
    command "$a"
done
shopt -u nullglob
share|improve this answer

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.