25

NOTE: this question used to be worded differently, using “with/out newline” instead of “with/out empty line”

I have two files, one with an empty line and one without:

File: text_without_empty_line

$root@kali:/home#cat text_without_empty_line
This is a Testfile
This file does not contain an empty line at the end
$root@kali:/home#

File: text_with_empty_line

$root@kali:/home#cat text_with_empty_line
This is a Testfile
This file does contain an empty line at the end

$root@kali:/home#

Is there a command or function to check if a file has an empty line at the end? I already found this solution, but it does not work for me. (EDIT: IGNORE: A solution with preg_match and PHP would be fine as well.)

törzsmókus
  • 1,799
  • 2
  • 21
  • 28
Black
  • 18,150
  • 39
  • 158
  • 271

4 Answers4

32

Just type:

cat -e nameofyourfile

If there is a newline it will end with $ symbol. If not, it will end with a % symbol.

Tom Aranda
  • 5,919
  • 11
  • 35
  • 51
Camila Masetti
  • 321
  • 3
  • 2
22

Olivier Pirson's answer is neater than the one I posted here originally (it also handles empty files correctly). I edited my solution to match his.

In bash:

newline_at_eof()
{
    if [[ -s "$1" && -z "$(tail -c 1 "$1")" ]]
    then
        echo "Newline at end of file!"
    else
        echo "No newline at end of file!"
    fi
}

As a shell script that you can call (paste it into a file, chmod +x <filename> to make it executable):

#!/bin/bash
if [[ -s "$1" && -z "$(tail -c 1 "$1")" ]]
then
    echo "Newline at end of file!"
else
    echo "No newline at end of file!"
fi
Fred
  • 391
  • 1
  • 4
  • Thank you. Can you provide the whole script pls and describe how to use it, i am a newbie to bash scripting. I don't get any output. – Black Jan 22 '16 at 10:17
  • 1
    Make sure your interpreter is `#!/bin/sh` at the top of the file, then just add the function and then `newline_at_eof "$1"` after the function. Or just use the following as line 2 and forget the function `test $(tail -c 1 $1) && printf "no newline at eof: $1\n" || printf "newline at eof: $1\n"` – David C. Rankin Jan 22 '16 at 10:25
  • Thank you, now the script works. But i always get "Newline at end of file!"... even on files which contain only one single line! – Black Jan 22 '16 at 10:29
  • 1
    I edited my answer to include the whole script. It should work on files with an arbitrary number of lines (tested on Debian stretch amd64, bash 4.3-14+b1, coreutils 8.23-4). – Fred Jan 22 '16 at 11:47
  • 1
    @EdwardBlack You should always get `newline at eof` even with a 1 line file because POSIX specifies that all `files` end with a newline (regardless of the number of lines). Note: that doesn't mean they will. There are a lot of editors that write non-POSIX compliant line endings. – David C. Rankin Jan 22 '16 at 12:29
  • I already read about this, but in my case my files are for a server configuration and it won't work if there is a space, tab or newline at the end, so i have to remove them. – Black Jan 22 '16 at 12:34
  • 1
    (@Fred `else` after an `exit` is superfluous.) – Biffen Jan 22 '16 at 12:37
  • Isn't that what they call *re-entrant* (you leave and then come back to finish the `if` block ? `:)` – David C. Rankin Jan 22 '16 at 12:39
  • I think it's better to use `echo` instead of `exit` since the later indicates whether [there's an error with the process](https://stackoverflow.com/a/47177028/3184351). – GNUSupporter 8964民主女神 地下教會 Dec 24 '18 at 16:32
  • `exit` is sometimes useful if comparing the exit status to some value is easier than comparing the output of the program (e.g. integer vs. string comparison). Also, [this answer](https://stackoverflow.com/a/40484670/3995440) explaisn quite well that there are no real conventions for exit codes rather than 0 and 2. For example, `diff` returns 1 if the files differ. That's hardly an error with the process. – Fred Dec 26 '18 at 23:09
  • 1
    Empty file is a special case which must be check separately. One way is to complete by: if [[ -s "$1" && -z "$(tail -c 1 "$1")" ]] – Olivier Pirson Aug 13 '20 at 14:40
3

I found the solution here.

#!/bin/bash
x=`tail -n 1 "$1"`
if [ "$x" == "" ]; then
    echo "Newline at end of file!"
else
    echo "No Newline at end of file!"
fi

IMPORTANT: Make sure that you have the right to execute and read the script! chmod 555 script

USAGE:

./script text_with_newline        OUTPUT: Newline at end of file!
./script text_without_newline     OUTPUT: No Newline at end of file!
David Pal
  • 5
  • 3
Black
  • 18,150
  • 39
  • 158
  • 271
  • This checks whether the last *two* characters are newlines. A much more interesing problem, which probably most people assume you are asking, is how to identify invalid text files which have text after the final newline. – tripleee Jan 22 '16 at 13:55
2

The \Z meta-character means the absolute end of the string.

if (preg_match('#\n\Z#', file_get_contents('foo.txt'))) {
    echo 'New line found at the end';
}

So here you are looking at a new line at the absolute end of the string. file_get_contents will not add anything at the end. BUT it will load the entire file into memory; if your file is not too big, its okay, otherwise you'll have to bring a new solution to your problem.

JesusTheHun
  • 1,217
  • 1
  • 10
  • 19
  • Thank you. But I just tried it and i always get "New line found at the end", even though there is no newline. Try it by yourselve. – Black Jan 22 '16 at 10:12
  • I always try before submitting. It works properly. Maybe it's your text editor that automatically end a new line at the end, like `nano` does. – JesusTheHun Jan 22 '16 at 10:13
  • Which text editor should i use instead of `nano`? – Black Jan 22 '16 at 10:23
  • 1
    `vi` for exemple. Press `i` to be in edit mode, `esc` to exit edit mode, and `:qw` to exit program saving changes. – JesusTheHun Jan 22 '16 at 10:26
  • I created a single liner with `vi` but i still get "New line found at the end", are you sure that your code works properly? – Black Jan 22 '16 at 10:31
  • Did you copy exactly my code ? Because I've try it again and again and it just works. – JesusTheHun Jan 22 '16 at 10:34
  • 1
    On the bottom of the screen in vi, you should see "[Incomplete last line]" meaning there is actually no new line at the end. – JesusTheHun Jan 22 '16 at 10:36
  • I made a screenshot, unfortunattely i don't know how to upload pictures in the comment section, so i uploaded it to pasteall: http://www.pasteall.org/pic/show.php?id=98003 There is no `[incomplete last line]` – Black Jan 22 '16 at 10:40
  • 1
    This is super weird. If you do `php -r 'echo nl2br(file_get_contents("/var/www/html/textohne_newline"));'` , do you see a "
    " at the end ?
    – JesusTheHun Jan 22 '16 at 10:54
  • yes there is a `
    ` at the end if i do this, hmm weird. Do you know why this is added?
    – Black Jan 22 '16 at 11:01
  • Maybe check this : http://stackoverflow.com/questions/1050640/vim-disable-automatic-newline-at-end-of-file – JesusTheHun Jan 22 '16 at 11:09
  • If your question is answered, don't forget to mark the correct answer. – JesusTheHun Jan 22 '16 at 12:42