9

in this script i end up with "$1" being saved to the /test file.

#!/bin/bash
cat > /test << 'EOF'
$1
EOF

the truth is.. i need to keep

'EOF'

as 'EOF' because my argument($1) contains dollar signs.

but i need that argument to be saved rather than $1

  • 1
    'because my argument($1) contains dollar signs.' Not if it refers to the first command line parameter. Substitution was performed on that before your script executed. You have to escape it on the command line. – goldilocks Jun 21 '14 at 9:27
  • You've asked several related questions about this task you're doing, and the progression of questions shows that you don't really understand what's going on and are probably not choosing the easiest approach. It's difficult to help you without knowing what you're trying to do, so I recommend that you ask a question where you clearly explain your overall task and don't constrain the answers to use a particular tool. For example, don't say “I want to use cat and keep dollar signs”, but “I want to modify the httpd.conf to change <some setting> in <this manner>”. – Gilles 'SO- stop being evil' Jun 21 '14 at 12:20
  • @Gilles, ultimately i decided to write to a different file via python and then use a bash script to write that file to the original file that was edited. this process is much easier . cat /temp_file > $1 – user72685 Jun 21 '14 at 12:22
  • @Gilles, the reason why my questions do not make sense is because the way bash scripts handle variables passed on to them. there are too many things that have to be escaped and yet there is not a feature to encode and decode on the fly. – user72685 Jun 21 '14 at 12:26
  • @Gilles, the only thing that made sense to me a bit was base64 but why must one have to encode their stuff in order to pass to a bash script.. escaping things and then trying to re-construct things within the bash script.. the whole three forward slashes to escape a backtick and etc.. it seems to me like a code hell – user72685 Jun 21 '14 at 12:28
14

Following up on your previous question, it sounds like you want both some uninterpreted text and some interpreted text going into a file. In that case, use two different cats (or echos):

cat > /test <<'EOF'
some uninterpreted text $(pwd)
not substituted: $1
EOF
cat >> /test <<EOF
but this will substitute: $1
EOF

There's a couple of things going on here: firstly, the heredoc syntax with <<. If you include quotes in that terminator string, as in the first one above, the entire heredoc is uninterpreted — no parameters and no substitutions. If you don't use any quotes, like in the second cat above, variables like $1 will be replaced by their values and command substitutions will be included in the text. You choose between whether to quote the "EOF" string or not based on whether you want substitutions or not.

To put both cats into the same file we're using >> redirection for the second (and any later) redirections: that means to append to the file. For the first one, we use a single > to clear the file out and start fresh.

Note that, even when variables are substituted, any additional dollar signs in that variable's value aren't re-substituted themselves:

foo='$bar'
bar=hello
cat <<EOF
$foo
EOF

will output:

$bar

without substituting in $bar's value.

However, if you're providing a "$" in the argument to this whole script, you need to escape it on the command line or enclose the whole thing in single quotes. Alternatively, command substitution as in your other question lets you put the contents of a whole file in directly, including any dollar signs in the file contents. Make sure you quote the substitution string there:

oo.sh "$(cat myfile)"

will get the body of myfile as $1 and can then cat or echo it as required. The same limitations as in my answer there apply: there's a limit for how long the command-line arguments can be, and if your file might get longer than that you should find another approach. You can find out what the limit is on your system with getconf ARG_MAX

1

Sounds like you simply want to output the one variable to the file. In that case, this will work:

echo $1 >/test

Note that /test is in the root directory, which ordinary users don't usually have write permission for.

EDIT: Bear in mind that you need to quote the dollar-sign-containing string in the command line. That is where the substitution occurs, and the script can't do anything about it after the fact.

  • I think you have the correct answer now. +1 – goldilocks Jun 21 '14 at 9:28
  • @MichaelHomer's answer is much more complete and includes useful information about here documents that I'd forgotten. His answer should be accepted (unless someone else posts an even better one, of course). – Tom Zych Jun 21 '14 at 9:55

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