Why the following command does not inserts new lines in the generated file and what's the solution?

$echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2
up vote 30 down vote accepted

echo


An echo implementation which strictly conforms to the Single Unix Specification will add newlines if you do:

echo 'line1\nline2'

But that is not a reliable behavior. In fact, there really isn't any standard behavior which you can expect of echo.

OPERANDS

string

A string to be written to standard output. If the first operand is -n, or if any of the operands contain a <\backslash> character, the results are implementation-defined.

On XSI-conformant systems, if the first operand is -n, it shall be treated as a string, not an option. The following character sequences shall be recognized on XSI-conformant systems within any of the arguments:

\a - Write an <alert>.

\b - Write a <backspace>.

\c - Suppress the <newline> that otherwise follows the final argument in the output. All characters following the \c in the arguments shall be ignored.

\f - Write a <form-feed>.

\n - Write a <newline>.

\r - Write a <carriage-return>.

\t - Write a <tab>.

\v - Write a <vertical-tab>.

\\ - Write a <backslash> character.

\0num - Write an 8-bit value that is the zero, one, two, or three-digit octal number num.

And so there really isn't any general way to know how to write a newline with echo, except that you can generally rely on just doing echo to do so.

A bash shell typically does not conform to the specification, and handles the -n and other options, but even that is uncertain. You can do:

shopt -s xpg_echo
echo hey\\nthere

hey
there

And not even that is necessary if bash has been built with the build-time option...

--enable-xpg-echo-default

Make the echo builtin expand backslash-escaped characters by default, without requiring the -e option. This sets the default value of the xpg_echo shell option to on, which makes the Bash echo behave more like the version specified in the Single Unix Specification, version 3. See Bash Builtins, for a description of the escape sequences that echo recognizes.


printf


On the other hand, printf's behavior is pretty tame in comparison.

RATIONALE

The printf utility was added to provide functionality that has historically been provided by echo. However, due to irreconcilable differences in the various versions of echo extant, the version has few special features, leaving those to this new printf utility, which is based on one in the Ninth Edition system.

The EXTENDED DESCRIPTION section almost exactly matches the printf() function in the ISO C standard, although it is described in terms of the file format notation in XBD File Format Notation.

It handles format strings which describe its arguments - which can be any number of things, but for strings are pretty much either %byte strings or literal %strings. Other than the %formats in the first argument, it behaves most like a %byte string argument, except that it doesn't handle the \c escape.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

See Why is printf better than echo? for more.


echo() printf


You might write your own standards conformant echo like...

echo(){
    printf '%b ' "$@\n\c"
}

...which should pretty much always do the right thing automatically.

Actually, no... That prints a literal \n at the tail of the arguments if the last argument ends in an odd number of <backslashes>.

But this doesn't:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac
  • +1 for the shopt -s xpg_echo option in echo to use -e by default. – Vignesh Raja Jun 8 at 13:54

Pass the -e flag to echo to make it parse escaped characters such as "\r\n", like so:

echo -e "Line 1\r\nLine2" >> readme.txt
  • A nice simple "-e" option to get escape sequences working - it says on another answer that echo is unreliable and doesn't follow standards unlike printf. – Edward Nov 22 '17 at 22:44
echo -e "Line 1\r\nLine2" >> readme.txt

further usage possibilities:

man echo

In all versions of bash I've used, you may simply insert a literal newline into a string either interactively or in a script, provided that the string is sufficiently quoted.

Interactively:

$ echo "Line one
> Line two"
Line one
Line two
$

In a script:

echo "Line one
Line two"

People have already answered adequately, but I refuse to accept a world where echo accepts any option other than -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

If you have a character that is not part of the message you can pipe through sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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