10

I want to get the last 10 lines of multiple files. I know they all end with "-access_log". So I tried:

 tail -10 *-access_log 

But this gives me an error, where as:

tail -10 file-*

Gives me the output I'd expect. I would think this probably has more to do with BASH then tail. However commands like:

cat *-access_log

Work fine.

Any suggestions?

3 Answers 3

10

I believe you would want:

tail -n 10 *-access.log

As to why:
I don't think it has anything to do with globbing:

tail -10 foo-access.log arf-access.log 
tail: option used in invalid context -- 1

I think it just so happens that your glob expands to one file. It probably has something to do with some archaic options parsing that I am too lazy to try to read, but if you really want to know go look in tail.c in the coreutils source and dissect the following function:

parse_obsolete_option (int argc, char * const *argv, uintmax_t *n_units)
3
  • or tail -n 10 *-access.log thanks for super fast reply!!
    – Mitch
    Apr 30, 2010 at 17:22
  • Ya, really you don't even need the 10 because that is the default. Apr 30, 2010 at 17:25
  • fyi, it seems it has to do with globbing (please read my answer)
    – Déjà vu
    Apr 7, 2013 at 10:26
6

While a bit old, the question is still relevant. I met a similar problem

ssh myserver.com 'tail -2 file-header*'

that gave me the error

tail: option used in invalid context -- 2

however, tailing only one file, like

ssh myserver.com 'tail -2 file-header-file-one'

works fine. Looking at the source tail.c shows that tail starts by parsing obsolete options, then parse the rest (i.e. options not processed yet), regular options. However, parse_obsolete_option() expects an "obsolete" usage, with only one file as argument.
So when providing more files, the function returns immediately, and let the regular parser to choke on -2 (expecting -n 2).

  /* With the obsolete form, there is one option string and at most
     one file argument.  Watch out for "-" and "--", though.  */
  if (! (argc == 2
         || (argc == 3 && ! (argv[2][0] == '-' && argv[2][1]))
         || (3 <= argc && argc <= 4 && STREQ (argv[2], "--"))))
    return false;

In conclusion, it is better to always use the -n regular form, knowing that the "obsolete" code only accepts one file.

1
  • 2
    Love that you dug into the source and found the root cause of this problem! But yeah, in conclusion, use -n 2 instead of -2 when there are wild cards.
    – ADTC
    Jul 30, 2015 at 5:44
0

Actually this behavior of GNU tail(-COUNT only accepts one file) is documented. https://www.gnu.org/software/coreutils/manual/html_node/tail-invocation.html

For compatibility tail also supports an obsolete usage ‘tail -[num][bcl][f] [file]’, which is recognized only if it does not conflict with the usage described above. This obsolete form uses exactly one option and at most one file.

It could also be found in coreutils info page installed.

shell> info tail

Note that on the contrary, "head -COUNT" supports multiple files.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .