1

I need to write a user supplied command to a file with bash.

Testcase would be script.sh -- echo "Hello \$USER" and I want a file containing echo "Hello $USER" (or echo Hello\ $USER) which can be executed

I'm using heredoc to write to the file, so something like

cat > "${FILE}" <<EOF
Your command is:
${CMD}
"$@"
EOF

I tried using printf -v CMD '%q ' "$@" but that leads to echo Hello\ \$USER which is not what I want.

How do I do this?

5
  • is there any reason you are using %q format ? because i just tried with the %s and it worked Commented Apr 16, 2019 at 15:54
  • You could use $* like so printf "Your command is $*\n" Commented Apr 16, 2019 at 15:55
  • The problem is quotes/spaces: Using $* or %s will lead to echo Hello $USER -> 2 arguments instead of 1. This is a problem for e.g. cat "foo with bar" -> cat foo with bar Commented Apr 16, 2019 at 16:34
  • 1
    You want the space to be quoted but not the dollar sign? If so you're going to have to do some manual string manipulation; there's no escaping mechanism that's going to clairvoyantly know to quote one but not the other. Commented Apr 16, 2019 at 16:37
  • 1
    The problem starts with what's being fed to the script. Can you just have the user quote the entire string? script.sh -- 'echo "Hello $USER"' would be a piece of cake to deal with. Commented Apr 16, 2019 at 16:39

1 Answer 1

1

Based on the suggestion to do it manually I came up with the following using this reasoning:

  • "$@" syntax means: Expand all args to "$1" "$2" ...
  • This seems not to work in my case, so do it manually:
    CMD=()
    for var in "$@"; do
        CMD+=( '"'"${var}"'"' )
    done

    cat > ${FILE} <<EOF
    Your command is: 
    ${CMD[@]}

So basically: Create an array of quoted strings. Then print this. This works for the testcase.

But: It fails for plenty of other things. Example: myScript.sh -- echo "Hello \"\$USER\"" which leaves the quotes unescaped.

So I conclude that this task is not possible or at least not feasible and would suggest to use the printf based solution which seems to be also how other commands handle it (example: srun/sbatch on SLURM)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.