318

When I execute commands in Bash (or to be specific, wc -l < log.txt), the output contains a linebreak after it. How do I get rid of it?

hexacyanide
  • 88,222
  • 31
  • 159
  • 162

9 Answers9

424

If your expected output is a single line, you can simply remove all newline characters from the output. It would not be uncommon to pipe to the tr utility, or to Perl if preferred:

wc -l < log.txt | tr -d '\n'

wc -l < log.txt | perl -pe 'chomp'

You can also use command substitution to remove the trailing newline:

echo -n "$(wc -l < log.txt)"

printf "%s" "$(wc -l < log.txt)"

If your expected output may contain multiple lines, you have another decision to make:

If you want to remove MULTIPLE newline characters from the end of the file, again use cmd substitution:

printf "%s" "$(< log.txt)"

If you want to strictly remove THE LAST newline character from a file, use Perl:

perl -pe 'chomp if eof' log.txt

Note that if you are certain you have a trailing newline character you want to remove, you can use head from GNU coreutils to select everything except the last byte. This should be quite quick:

head -c -1 log.txt

Also, for completeness, you can quickly check where your newline (or other special) characters are in your file using cat and the 'show-all' flag -A. The dollar sign character will indicate the end of each line:

cat -A log.txt
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Steve
  • 51,466
  • 13
  • 89
  • 103
  • This strips ALL newlines from the output, not just the trailing newline as the title asks. – Cody A. Ray Dec 11 '14 at 17:52
  • @CodyA.Ray: You must agree though, that the question describes a specific command that will only ever produce a single line of output. I have, however, updated my answer to suit the more general case. HTH. – Steve Dec 12 '14 at 00:32
  • 5
    This would be better if the short options were replaced with long options. The long options teach as well as function e.g. `tr --delete '\n'`. – Elijah Lynn Apr 05 '16 at 13:10
  • 2
    I also did `| tr -d '\r'` – AlikElzin-kilaka Jul 20 '16 at 09:16
  • It's worth noting that the cmd substitution solution might lead to an overlong line if the file is very big. – phk Apr 25 '17 at 20:03
  • 2
    My up-vote is for the `head -c ... ` version -- Because I can _now_ feed commands to the clipboard and preserve formatting, but for the last `\n`. Eg.: `alias clip="head -c -1 | xclip -selection clipboard"`, not too shabby. Now when you pipe `ls -l | clip` ... All that wonderful output goes to the X-Server `clipboard` without a terminating `\n`. Ergo ... I can paste that into my next command, _just so_. Many thanks! – will Aug 17 '18 at 14:24
  • Any reason for using `head -c -1` instead of `head -n -1`, given that we know that it's a newline? – lindhe Aug 17 '23 at 13:39
96

One way:

wc -l < log.txt | xargs echo -n
hexacyanide
  • 88,222
  • 31
  • 159
  • 162
Satya
  • 4,458
  • 21
  • 29
  • 26
    Better: `echo -n \`wc -l log.txt\`` – Satya Sep 30 '13 at 04:05
  • 11
    Why is doing command execution in backticks better than using a pipe? – Matthew Schinckel Sep 09 '14 at 07:05
  • 4
    These will not only remove the trailing newlines, but also squeeze any consecutive whitespaces (more precisely, as defined by `IFS`) to one space. Example: `echo "a b" | xargs echo -n`; `echo -n $(echo "a b")`. This may or may not be a problem for the use case. – musiphil Sep 15 '14 at 18:16
  • 16
    Worse, if the output begins with `-e`, it will be interpreted as the option to `echo`. It's always safer to use `printf '%s'`. – musiphil Sep 15 '14 at 18:17
  • 1
    `xargs` is very slow on my system (and I suspect it is on other systems too), so `printf '%s' $(wc -l log.txt)` might be faster, since `printf` is usually a builtin (Also because there is no information redirection). Never use backticks, they have been deprecated in newer POSIX versions and have numerous drawbacks. – yyny Mar 11 '18 at 23:12
27

If you want to remove only the last newline, pipe through:

sed -z '$ s/\n$//'

sed won't add a \0 to then end of the stream if the delimiter is set to NUL via -z, whereas to create a POSIX text file (defined to end in a \n), it will always output a final \n without -z.

Eg:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

And to prove no NUL added:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

To remove multiple trailing newlines, pipe through:

sed -Ez '$ s/\n+$//'
Tom Hale
  • 40,825
  • 36
  • 187
  • 242
  • 9
    I suppose this is a GNU extension, Mac `sed` doesn't provide `-z`. – Spidey Apr 13 '20 at 19:05
  • 1
    You can install gnu version of sed on mac, as `gsed` and use it, by [doing what it says here](https://stackoverflow.com/q/30003570/26510) – Brad Parks Jun 17 '21 at 11:18
  • 1
    Can someone explain what the `$ ` in the beginning of the sed expression does? – what the Dec 05 '21 at 22:07
  • If I interpret it correctly, the `$` is for selecting the last line and thus to avoid executing the `sed` command on all lines. See https://www.gnu.org/software/sed/manual/sed.html#Numeric-Addresses – dwettstein Jan 03 '22 at 22:25
23

There is also direct support for white space removal in Bash variable substitution:

testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
Heath Borders
  • 30,998
  • 16
  • 147
  • 256
Andrey Taranov
  • 520
  • 4
  • 10
  • 4
    You can also use `trailing_linebreak_removed=${testvar%?}` – PurplProto Jul 11 '19 at 22:25
  • 1
    Note that if you are using command substitution then you don't need to do anything to remove trailing newlines. Bash already does that as part of command substitution: https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html – Michael Burr Jun 09 '20 at 01:33
13

If you want to print output of anything in Bash without end of line, you echo it with the -n switch.

If you have it in a variable already, then echo it with the trailing newline cropped:

$ testvar=$(wc -l < log.txt)
$ echo -n $testvar

Or you can do it in one line, instead:

$ echo -n $(wc -l < log.txt)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
10

If you assign its output to a variable, bash automatically strips whitespace:

linecount=`wc -l < log.txt`
nneonneo
  • 171,345
  • 36
  • 312
  • 383
10

printf already crops the trailing newline for you:

$ printf '%s' $(wc -l < log.txt)

Detail:

  • printf will print your content in place of the %s string place holder.
  • If you do not tell it to print a newline (%s\n), it won't.
zero2cx
  • 482
  • 6
  • 19
  • 10
    If you put double quotes around the command like `"$(command)"`, the internal newlines will be preserved -- and only the *trailing* newline will be removed. The shell is doing all the work here -- `printf` is just a way to direct the results of command substitution back to `stdout`. – Brent Bradburn Dec 08 '14 at 17:29
  • 3
    It's not printf that's stripping the new line here, it's the shell that's doing it with the `$( )` construct. Here's proof: `printf "%s" "$(perl -e 'print "\n"')"` – Flimm Feb 11 '15 at 11:25
  • Again, it's worth noting that the resulting command line might become too long. – phk Apr 25 '17 at 20:04
  • This is a convenient solution with @nobar's suggestion: `$ printf '%s' "$(wc -l < log.txt)"` – Ilias Karim Jul 01 '18 at 05:47
7

Adding this for my reference more than anything else ^_^

You can also strip a new line from the output using the bash expansion magic

VAR=$'helloworld\n'

CLEANED="${VAR%$'\n'}"

echo "${CLEANED}"
1

Using Awk:

awk -v ORS="" '1' log.txt 

Explanation:

  1. -v assignment for ORS
  2. ORS - output record separator set to blank. This will replace new line (Input record separator) with ""
Rakesh Gupta
  • 3,507
  • 3
  • 18
  • 24
  • 1
    -1 (though I did not actually press the button for it since I would only be allowed to change it once). This removes *all* newlines, not just any leading or trailing ones. – Melab Jul 13 '21 at 20:33