5

I write this in terminal:

printf ' \n\necho -e \"writes (>> appends) in note.txt this text'\n'on 2lines (with "-e" and "'\n'" help)\" >> note.txt\n' > note.txt 

I get this in note.txt:

echo -e "writes (>> appends) in note.txt this textnon 2lines (with "-e" and "n" help)" >> note.txt

I want to get this in note.txt:

echo -e "writes (>> appends) in note.txt this text\non 2lines (with "-e" and "\n" help)" >> note.txt

(\- is missing)

Eliah Kagan
  • 117,780

5 Answers5

8

Way 1: Escape instances of \ that you don't want to escape other characters.

Based on the contents of your string, you probably want:

echo -e 'writes (>> appends) in note.txt this text\non 2 lines (with "-e" and "\\n" help)' >> note.txt

The text this appends to note.txt is:

writes (>> appends) in note.txt this text
on 2 lines (with "-e" and "\n" help)

The changes are:

  • You had /n where it looked like you wanted a line break. So I changed that to \n.
  • In the text with "-e" and "\n", the \ is intended to be printed literally rather than to combine with the n following it and produce a newline. So I quoted (escaped) \ with another \. If \n produces a new line, \\n produces \n.
  • I replaced the outer double quotes (") with single quotes ('). You wanted the " characters around -e and \n to be printed literally, but instead they ended and restarted quoting, preventing them from being printed and causing \n to actually be printed as n (because an unquoted \n is processed before being passed to echo). An alternative solution would have been to write \" for the inside " characters. But there was no reason to enclose the whole thing in double quotes--single quotes are usually preferable in cases where either can be used.

    The other change--which was not a change in the final command but was a change I made just while working on it--was that I removed the >> note.txt redirection until I knew I had the command right. By sending output to the terminal, I was immediately able to see what the effect was. I re-added the redirection when I was done.

That's stylistically closest to what you already had, but it's not the only way to do it.

Way 2: Separate echo commands for separate lines, instead of using -e.

Since the only sequence you want treated specially by echo is the \n (between text and on), you can just use two separate echo commands and (as muru may be suggesting) not use -e.

Here are two ways of redirecting the output of multiple commands:

  1. Two separate redirections, one for each command.

    echo 'writes (>> appends) in note.txt this text' >> note.txt
    echo 'on 2 lines (with "-e" and "\n" help)' >> note.txt
    

    If the filename is long or you're writing a script and only want to have to change it in one place, you can assign it to a variable:

    out="/home/ek/Documents/long name that can have spaces as it's quoted/note.txt"
    echo 'writes (>> appends) in note.txt this text' >> "$out"
    echo 'on 2 lines (with "-e" and "\n" help)' >> "$out"
    
  2. A single redirection applied to a compound command composed of the two commands.

    {
        echo 'writes (>> appends) in note.txt this text'
        echo 'on 2 lines (with "-e" and "\n" help)'
    } >> note.txt
    

    You can put that on one line if you like, but if there's no newline before the closing brace (}), a semicolon (;) must precede it:

    { echo 'writes (>> appends) in note.txt this text'; echo 'on 2 lines (with "-e" and "\n" help)'; } >> note.txt

Way 3: Pass a literal \n to echo instead of using -e.

Real newlines can appear inside quotes (single or double) and are interpreted literally:

echo 'writes (>> appends) in note.txt this text
on 2 lines (with "-e" and "\n" help)' >> note.txt

Because the first line ends inside quotes, the shell doesn't take it as the end of the command, but instead continues reading.

If you do want to fit it on a single line, you can use $'\n', which expands to a newline. This is expanded by the shell before being passed to the echo command, so it should not be quoted.

echo 'writes (>> appends) in note.txt this text'$'\n''on 2 lines (with "-e" and "\n" help)' >> note.txt

Way 4: Use printf

printf is very powerful; there are a number of ways you could use it to solve this problem. Since I am presenting this as a distinct solution from the others, here's a good way to use it in a way you cannot use echo:

printf '%s\n%s\n' 'writes (>> appends) in note.txt this text' 'on 2 lines (with "-e" and "\n" help)' >> note.txt

The general syntax for printf is printf format args... (where args... means zero or more additional command-line arguments). The format string above, %s\n%s\n, means:

  1. %s: consume and print the next unused (i.e., first) argument in args... (i.e., your 1st line).
  2. \n: print a newline.
  3. %s: consume and print the next unused (i.e., second) argument in args... (i.e., your 2nd line).
  4. \n: print a newline.

When there are more arguments after the format string than the format string calls for, the printf command starts over from the beginning of the format string. Thus, while less self-documenting, you could actually write just '%s\n' (instead of '%s\n%s\n') for the format string, and it would produce the same output in this case.

I will not attempt to broadly document printf here. Instead, see:

Way 5: Use cat and a here document.

This way is especially valuable when there's a lot of input, and when scripting. If you're using the shell interactively rather than writing a script, you can use this, but please consider Way 6 below first.

While echo and printf print text based on the contents of their command-line arguments, cat prints the contents of its input files (as specified on the command line) or, if given none (or passed -), its standard input.

With no redirections, standard input is what you type on a program's controlling terminal. Here documents are a special kind of redirection. Lines are collected until a specified keyword (I've used EOF) appears by itself on a line. Then the lines up to but not including EOF (or whatever you used) are given as standard input to the command being run.

cat >> note.txt << EOF
writes (>> appends) in note.txt this text
on 2 lines (with "-e" and "\n" help)
EOF

One of the differences between quoting with " and ' is that most expansions and substitutions with $ (e.g., $varname) are performed in double quotes, but none are in single quotes. There are also two ways to use here documents, based on whether $ (and also ` and \) are to be given special meaning or treated literally.

In this case, it doesn't matter--$ and ` don't appear, and \ is only treated specially in a here document when it escapes a shell metacharacter (not n). Just as in single and double quoted expressions, both ways treat \n literally. (Remember, you had to use a special feature of echo, turned on by -e, to get \n treated specially.)

But so you know for other applications:

  • The way shown above will perform expansions and substitutions, treating $, `, and \ specially when they appear in a context where their special meaning applies.
  • To cause all text to be treated literally, quote all or part of the word appearing to the right of << with ', ", \, or a combination thereof (e.g., cat >> note.txt << 'EOF').

Way 6: Use cat without any input redirection.

If you're using the shell interactively, by default the shell's standard input is taken from your terminal. When you then run a program, by default that program's standard input is taken from your terminal too. (This may be changed by input redirections, of course.)

So if you're running a command interactively and want to use cat with >> or > output redirection to send data to a file, you don't need any input redirection. Just enter:

cat >> note.txt
writes (>> appends) in note.txt this text
on 2 lines (with "-e" and "\n" help)
^D

In place of ^D, don't enter a literal ^D. Instead, press Ctrl+D. That signals to your terminal that it should report end of file (i.e., that when the running program asks for more input, it is told that there is none left, just as if it had reached the end of a regular file stored on disk). When cat sees there's no more input, it exits, and you are returned to the shell.

If you're writing a script, Way 6 will not work, because bash reads commands from a file but standard input is still (typically) a something else, such as your terminal.

One notable difference between using cat with a here document and using cat with no input redirection, even when standard input is your terminal, is that:

  • cat >> note.txt writes one line at a time to note.txt. Each time you press Enter, a line is written to note.txt.
  • cat >> note.txt << EOF takes all input up to the EOF line, then appends it to note.txt. If you interrupt the input by pressing Ctrl+C, nothing is written (and if note.txt didn't exist already, it is not even created).
Eliah Kagan
  • 117,780
1

Well, I hope this satisfies your needs:

  1. Press, Ctrl+Alt+T
  2. Type, in the following command:
    nano
  3. An editor in the terminal would open for you.
  4. Type in whatever you want, in your case:
    echo -e 'writes(>> appends) in note.txt this text/non 2lines (with "-e" and "\n" help)' >> note.txt (that's what I got from your question)
  5. To Save and Exit,
    • Press, Ctrl+X
    • Will ask for a confirmation message to save, press y
    • Type, a name for your file, press Enter
  6. To Check,
    • Open File Manager, you'll see a file that you saved.
    • You'll, probably find all your text (including, "\n")
devGeek
  • 594
1

The shell interperlates special characters like the backslash, except when it's surrounded by single quotes.

echo takes arguments beginning with dash, so to be extra safe, you should use printf instead, like this:

$ printf %s 'A \n B \n'
A \n B \n

%s just means print the string I'm passing as an argument. It's often used like this:

$ variable=Flimm
$ printf '%s is all right\n' "$variable"
Flimm is all right

You can find out more about the Bash's interpolation in the manpage for the bash command Manpage icon, search for the section entitled QUOTING. Also look at the manpage for the printf command Manpage icon.

Flimm
  • 41,766
1

The character \ is also an escape character for itself, so you can add an additional \ like so:

mgodby@mg-ws1:~$ echo -e '\n'


mgodby@mg-ws1:~$ echo -e '\\n'
\n
mgodby@mg-ws1:~$ 
Eliah Kagan
  • 117,780
MGodby
  • 1,162
  • dear god it works:D so the solution was to use '' single quotes, and /, I feel stupid now but at least I learned something TYall –  Oct 07 '14 at 20:57
0

one more way:

perl -e 'print q{
this preserves \n backslash-n
and other special characters except close-squiggle 
(without a matching open-squiggle, which would be very rare)
}' > note.txt

if your note has a close-squiggle you can chose another delimeter to the q() function:

perl -e 'print q|

this works even with an unmatched close-squiggle
like this one: }

but it doesnt workt if i have a pipe in my text...

|' > note.txt

of course all these methods (perl or native printf) will fail if you have a single-quote inside your document. in this case you may be able to use double-quotes (so long as you dont have both single and double inside your text) eg


printf %s " I'm an idiot"