0

I'm looking for a good portable way of finding the oldest file in a directory tree matching a pattern, explicitly without using find's -printf option. So far I found this solution: https://superuser.com/a/552609/1182477 which I extend with a pattern like this:

find . -type f -name "*.csv" -print0 | xargs -0 ls -ltr | head -n 1

But this fails silently when no file matches the pattern. I get the oldest file regardless of the pattern. My diagnosis so far: when nothing matches the pattern, nothing gets passend into xargs and thus ls -ltr lists all files. How can I solve this? I want to get nothing out, when nothing matches the pattern.

And maybe, as a bonus, a solution that also avoids the ARG_MAX problem with long file lists? (And before someone asks: logrotate is not available on the system.)

One thing that I stumpled upon in my diagnostics and what could help me find a solution to the above:

ls *.csv

lists files matching that pattern. But

*.csv | xargs ls

lists all files. Shouldn't both of them do the same?

Thank You very much.

xenoid
  • 9,782
  • 4
  • 20
  • 31
PeterK
  • 1
  • Define "portable". POSIX? Also runs in Windows? – xenoid May 31 '20 at 12:19
  • The command `xargs` has an option `-r` which prevents the command from running if there list of arguments is empty. – Kapil May 31 '20 at 13:12
  • @xenoid: look at the tags, so no windows. I'm not so sure which platforms I should aim at. All I know, I'm running busybox, and there's no -printf option in find. – PeterK May 31 '20 at 14:51
  • @Kapil: Thank You for leaving the reputation of a good answer to me. ;-) – PeterK May 31 '20 at 14:56

2 Answers2

1

With busybox, your question can be answered by simply doing:

find . -type f -name "*.csv" -exec stat -c '%y %n'  {} + | sort | head -1

(removing the time stamp from the final result is left as an exercise for the reader)

This also avoids the SIGPIPE error you can get with your xargs-based version if there are very many files (unless you use this trick)

xenoid
  • 9,782
  • 4
  • 20
  • 31
  • I have no `stat` on this BusyBox v1.30.1. (It's a router running it.) Answer works on my Ubuntu 20.04. Thanks for pointing to the `tail -n +1` trick. But it doesn't relieve the signal 13 problem on neither systems. – PeterK Jun 01 '20 at 20:03
0

So, thanks to the comment of Kapil I found this working:

find . -type f -name "*.csv" -print0 | xargs -0r ls -ltr | head -n 1
PeterK
  • 1