Hi,

If one runs `head --lines=-0 somefile', he'll sometimes get no output instead 
of full file contents as
expected after reading the manual:

-n, --lines=[-]K
        print the first K lines instead of the first 10; with the lead‐
        ing `-', print all but the last K lines of each file

It depends on whether the file has a trailing newline.

For example:

$ printf '1\n2\n3' > test1
$ printf '4\n5\n' > test2
$ head -n -0 test*
==> test1 <==

==> test2 <==
4
5
$ tail -n +0 test*   # Just for comparison
==> test1 <==
1
2
3
==> test2 <==
4
5
$ 

I'm using Debian GNU/Linux 7 wheezy and coreutils-8.13; I've also tested 
coreutils-8.22, and it has the
same issue.

A proposed patch fixing the bug is attached. It makes head behave exactly like 
`tail -n +0' on same files.

-- 
Алексей Шилин
--- coreutils-8.22.orig/src/head.c	2013-12-04 14:48:30.000000000 +0000
+++ coreutils-8.22/src/head.c	2014-01-03 14:49:44.344272895 +0000
@@ -636,8 +636,11 @@
       return false;
     }
 
+  /* n_lines == 0 case needs special treatment. */
+  const bool all_lines = !n_lines;
+
   /* Count the incomplete line on files that don't end with a newline.  */
-  if (bytes_read && buffer[bytes_read - 1] != '\n')
+  if (n_lines && bytes_read && buffer[bytes_read - 1] != '\n')
     --n_lines;
 
   while (1)
@@ -647,11 +650,16 @@
       size_t n = bytes_read;
       while (n)
         {
-          char const *nl;
-          nl = memrchr (buffer, '\n', n);
-          if (nl == NULL)
-            break;
-          n = nl - buffer;
+          if (all_lines)
+            n -= n ? 1 : 0;
+          else
+            {
+              char const *nl;
+              nl = memrchr (buffer, '\n', n);
+              if (nl == NULL)
+                break;
+              n = nl - buffer;
+            }
           if (n_lines-- == 0)
             {
               /* Found it.  */

Reply via email to