0

I am looking for parameters to ls, or something equivalent, that do the following for a specified directory:

For each subdirectory:

  • Look at each file and directory it contains, recursively.
  • Find the file or directory with the most recent updated/modified date.
  • Show this recursive updated date.
  • Optionally, sort by this recursive updated date.

Afaik, the regular ls -lArt command only looks at the updated date of the folder itself, and not at the folder contents.

So, I am looking for an equivalent to what du -hs * | sort -h does for file size.


Example

Consider the following directory structure.

- dir
  - subdir1:        last udpated 2013-07-07
    - subdir1a:     last updated 2012-01-01
      * file1a1.txt last updated 2016-02-22
    * file1b.txt:   last updated 2016-01-06
    * file1c.txt:   last updated 2015-12-30

  - subdir2:        last updated 2016-03-10
    * file2a.txt:   last updated 2016-02-04

  * file3.txt:      last updated 2014-02-13

The output for ls-special dir (sorted) would be like this:

file3.txt: last updated 2014-02-13
subdir1:   last updated 2016-02-22
subdir2:   last updated 2016-03-10
6
  • Firstly, you don't seem to understand what du -hs * does. It bears no resemblance to what you describe. Secondly, ls has no option to do what you ask. Use find, sort and tail instead.
    – tink
    Mar 17, 2016 at 9:02
  • So, what have you tried? Mar 17, 2016 at 13:27
  • "it has no option to do what you ask. Use find, sort and tail instead." Ok fine, so the "or something equivalent" from my question applies. An answer that explains how to use find + sort + tail to achieve the above could be totally fine and in scope.
    – donquixote
    Mar 17, 2016 at 13:46
  • "Firstly, you don't seem to understand what du -hs * does." How so? I used it a dozen times today. It recursively aggregates the file size for each directory. Likewise, the command (combo) I am looking for recursively finds the most recent file update date for each directory. The intent is very similar. Technically it may be different, but so what.
    – donquixote
    Mar 17, 2016 at 13:48
  • I added an example to the question.
    – donquixote
    Mar 17, 2016 at 14:03

2 Answers 2

1

You need:

find . -type d -exec sh -c 'echo -n {}; cd "{}"; ls -ltd * | grep -v ^d | head -n 1 | awk "{\$1=\$2=\$3=\$4=\$5=\$6=\$7=\$8=\"\"; print \$0}"; echo"" ' \;

What this does: first locate all sub-directories of the starting directory, then execute the -exec part:

echo -n {}; cd "{}"; ls -ltd * | grep -v ^d | head -n 1 | awk "{\$1=\$2=\$3=\$4=\$5=\$6=\$7=\$8=\"\"; print \$0}"; echo""

This spawns a new shell (one per sub-directory), prints the sub-directory's name, moves into it, ranks by access time (-t) everything (i.e., files and directories) in long format (-l) without expanding the directories' content (-d). The long format is needed so that we can weed out directories (grep -v ^d), taking only the first line of output (head -n 1) which is the most recently accessed file, then (awk) we print only its name (not all other arguments), keeping in mind that its name might contain spaces: lastly, it prints a newline, so that directories with no content do not get mixed with the next one.

Keep in mind there is no way to distinguish ex aequos in modification time.

6
  • This does not provide a listing as in the example in the question. Instead of listing only the toplevel directories, it lists all subdirectories, recursively. And instead of showing the updated date/time for each list item, it just shows a file name per entry.
    – donquixote
    Mar 17, 2016 at 18:32
  • But chapeau for the effort. It looks complex :)
    – donquixote
    Mar 17, 2016 at 18:34
  • I think it would be easier and more transparent with "real" programming. That is, a script with loops and variables. Unfortunately I am really bad at shell script. I should familiarize myself with another language besides php, for this kind of stuff. (probably would be possible with php, but it just feels wrong)
    – donquixote
    Mar 17, 2016 at 18:36
  • @donquixote You know, the modifications needed to achieve what you wish are truly simple. Will you take care of them or do you want me to include them in my answer? Mar 17, 2016 at 19:18
  • If you don't mind including it, go ahead! I am currently still overwhelmed by too many levels of piping. It definitely should be part of the answer, so it matches the question (which I hope is more clear with the added example). If not for me, then for others who might find this.
    – donquixote
    Mar 17, 2016 at 19:59
1

The following command lists all files of the current tree (.) with newest file shown last:

find . -type f -printf "%T@ %p\n" | sort -n | awk '{print $2}' | xargs ls -lart

You must log in to answer this question.

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