7

System log files are serialized and I use ls -lrt to show me the most recent file. I then cat that file. This requires typing a long serial number each time.

How can I cat the last file appearing in my ls -lrt output in one command?

I'm using cygwin and the the output from ls -lrt foobar_job* look like this:

-

-rw-r--r-- 1 zundarz Domain Users   1133 Jul 31 16:54 foobar_job4855125.log
-rw-r--r-- 1 zundarz Domain Users   1256 Jul 31 17:10 foobar_job4855127.log
-rw-r--r-- 1 zundarz Domain Users   1389 Aug 11 10:20 foobar_job4887829.log
-rw-r--r-- 1 zundarz Domain Users   1228 Aug 11 10:39 foobar_job4887834.log
3
  • What is the output of a ls -lrt? The date format could be important.
    – Minix
    Aug 14, 2015 at 20:20
  • It's running bash.
    – zundarz
    Aug 14, 2015 at 20:36
  • I don't think you need the -l flag for ls Aug 14, 2015 at 21:30

4 Answers 4

18

If you're going to just cat a newest file in one command you don't really need -l option. On Linux and Cygwin you can use -1 option and make parsing much easier:

$ cat "$(ls -1rt | tail -n1)"

-1 should be very portable, it's specified in POSIX.

Also keep in mind that parsing ls output has its drawbacks.

EDIT:

As correctly noted in a comment by don_crissti you don't even need -1:

 $ cat "$(ls -rt | tail -n1)"
4
  • '-1' is really clever.
    – Minix
    Aug 14, 2015 at 20:28
  • 3
    @Minix - not really, it's not needed in this case. Per the same standard this answer links to: The default format shall be to list one entry per line to standard output; the exceptions are to terminals or when one of the -C, -m, or -x options is specified. So in this case, it's already one entry per line, run ls | cat to see how it works... Aug 14, 2015 at 20:49
  • @don_crissti: you're right, I added edit to my answer. Thx! Aug 14, 2015 at 21:01
  • @don_crissti Even more clever! Guess I should really read the man pages more.
    – Minix
    Aug 15, 2015 at 23:32
2

This method doesn't score highly in terms of correctness but should work in most cases: cat "$(ls -1t | head -n1)"

1

Tried it on my system and:

~$ cat "$(ls -lrt | tail -n 1 | tr -s ' ' | cut -d ' ' -f9-)"

worked.

ls -lrt

Gives the files ordered by their modification time (-t) in reverse order (-r).

tail -n 1

Gives you the last line of the output.

tr -s ''

Removes the repeat spaces in the line.

cut -d ' ' -f9-

Cuts the line on every space and gives you the 9th field, which is the file name. Adding - to the -f9 also gives all following fields, which is important for filenames containing spaces.

Alias

If you want to use the command as an alias, you have to escape the " characters.

That "'s in the command are necessary, because files can have spaces, which would be interpreted as more than one file by the cat command, if not enclosed by "'s.

It is also necessary to escape the $ sign. Otherwise the command inside $(...) would be executed once, when setting the alias and not every time the alias is called afterwards.

alias catrec="cat \"\$(ls -lrt | tail -n 1 | tr -s ' ' | cut -d ' ' -f9-)\""
2
  • I tried to make alias out of it: alias catrec=' <your command> ', but it's not parsed correctly, it returns an error -f9)" not found. BTW, you command is the only one that worked for me.
    – Konrad
    Dec 27, 2016 at 16:47
  • 1
    @Konrad That is because I also ' in my command. I will edit my answer to give a suitable solution.
    – Minix
    Dec 28, 2016 at 22:40
-1

Bash one-liner (provided your filenames do not contain spaces):

cat $(ls -lrt | tail -1 | rev | cut -d" " -f1 | rev)

Explanation:

tail -1        # get last line of your ls
rev            # reverse characters order
cut -d" " -f1  # take first field using space as a separator

So the rev | cut -d" " -f1 | rev thing is a trick to be sure to get the last space-separated word without having to provide a platform dependent field number of character offset.

3
  • I wasn't the one who downvoted your answer but it won't work with a file that has a whitespace in name, try it: echo bb > "awesome file" && cat $(ls -lrt | tail -1 | rev | cut -d" " -f1 | rev) Aug 14, 2015 at 20:31
  • I'm well aware of that, I should write it down. Aug 14, 2015 at 20:32
  • I think that you should fix your answer Aug 14, 2015 at 20:33

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