Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I don't remember the exact commands and tricks that I use sometimes which solves much of the work, so I try to log them into a file for future reference. What I typically do is just put whole command in echo and append it to the file quickly.

This has always worked, but the following situation arrived for first time, where I was not able to do as stated above.

Successfull logging

$ echo "cat file1.txt | paste -d, - - ## Step 3 " >> ~/globalLog.txt

Got stuck here

$ echo "cat file2.txt  | sed 's/"//g' > file3.txt ## Step 2 " >> ~/globalLog.txt

The above is giving a obvious error, as the quotes are not being properly closed (dropping to the second command propmt (PS2 I guess?) for completing the command i.e. >_ in my case), the single(') quotes are being used by the sed command and the double(") quotes are being used in one the sed expression for replacement.

How would I enclose the complete command in such situation ?

share|improve this question
    
It looks like you're trying to log a command before executing it. Are you aware of set -v and set -x? –  derobert Oct 24 '12 at 20:16

5 Answers 5

up vote 9 down vote accepted

You can entirely avoid the need to quote using here documents. Note that setting the label in single/double quotes(as in "EOF" in the example below) disables variable and command evaluation within the text.

cat <<"EOF" >>~/globalLog.txt
cat file2.txt  | sed 's/"//g' > file3.txt ## Step 2
EOF
share|improve this answer
    
This should work in any POSIX shell. –  jordanm Oct 24 '12 at 15:33
    
@jordanm, thank you. Deleted the reference to bash. –  1_CR Oct 24 '12 at 15:39
    
You might want to note the importance of the double-quotes around EOF. Without them, the here text is subject to variable expansion, which is sometimes useful. –  Dale Hagglund Oct 24 '12 at 15:43
    
@DaleHagglund, thank you. Incorporated. –  1_CR Oct 24 '12 at 15:53

You have many choices, and each of them can be convenient in different situations.

  1. Double quote the whole string as one, and escape the literal double quotes inside (easy to read if you have only one such occurrence, but you could end up with a picket fence):

    echo "cat file2.txt  | sed 's/\"//g' > file3.txt ## Step 2 " >> ~/globalLog.txt
    
  2. Use different quotes for the different parts of the string:

    echo "cat file2.txt  | sed 's/"'"'"//g' > file3.txt ## Step 2 " >> ~/globalLog.txt
    
  3. Use echo's ability to process multiple arguments. This is applicable if only a single word contains the offending character, since the result will typically have a space between each argument, so it won't work for your string. Alternative example:

    echo 'foo"' "'bar"
    

    prints

    foo" 'bar
    
  4. Use multiple echo -n statements (or printf %s) followed by an echo without -n:

    echo -n "cat file2.txt  | sed '" >> ~/globalLog.txt
    echo -n 's/"' >> ~/globalLog.txt
    echo "//g' > file3.txt ## Step 2 " >> ~/globalLog.txt
    
  5. Don't use quotes at all, but escape all special characters:

    echo cat\ file2.txt\ \ \|\ sed\ \'s/\"//g\'\ \>\ file3.txt\ \#\#\ Step\ 2\  >> ~/globalLog.txt
    

Note that it's not possible to escape single quotes in a single quoted string.

And if in doubt, Use More Quotes™.

In your case, however, it looks like you're logging a command before executing it. There's already a very nice solution for working with commands as text.

share|improve this answer
1  
My usual method (which is the simplest for programmatically quoting unknown data) is to enclose the whole thing in single quotes, then break out and backslash escape any that are inside. e.g. 'don'\''t' - this is similar to your "..."'"'"..." example but slightly easier to follow. –  Random832 Oct 24 '12 at 17:06

just escape the " like so:

echo "cat file2.txt  | sed 's/\"//g' > file3.txt ## Step 2 " >> ~/globalLog.txt
share|improve this answer
    
and remember to escape \`$ as well. It's easier to use single quotes. –  Gilles Oct 24 '12 at 21:57
    
the $ is only there to signify his shell, it has nothing to do with the command –  h3rrmiller Oct 25 '12 at 12:47

There is a simple, systematic and POSIX-compliant way to quote any string. You only need to remember two rules:

  1. Quote apostrophes (single quotes) with a backslash like so: \'
  2. Quote everything other than apostrophes by surrounding it with apostrophes like so: 'printf "foo\n"'

To illustrate how to use these rules together, the word don't can be systematically quoted like this: 'don'\''t'

You can often find a more readable way of quoting strings, but when things get complicated, this is the reliable way to get the quoting you want.

The quoted form of the string in the question is:

$ echo 'cat file2.txt  | sed '\''s/"//g'\'' > file3.txt ## Step 2 ' >> ~/globalLog.txt
share|improve this answer

Just

$ cat >> ~/globalLog.txt
<now type your command>
echo "cat file2.txt  | sed 's/"//g' > file3.txt ## Step 2 "
<hit ctrl-d>
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.