sort directories by last modified content (recursive)
The last modification time of a directory (think like phone directory, not folder) is the time it was last modified, like when an entry was removed, added or edited in that directory.
To find out the newest regular file recursively in it, you would need to read the contents of that directory and every directory within and for each file, check the file's modification time. That's a costly thing to do, I wouldn't expect any file manager application to do it.
You could however script it.
With the GNU implementations of find
and sort
(and any Bourne-like shell), you could do:
TZ=UTC0 find . -mindepth 2 -type f -printf '%TFZ%TT/%P\0' |
LC_ALL=C sort -zt/ -k2,2 -k1,1r |
LC_ALL=C sort -t/ -zmsuk2,2 |
LC_ALL=C sort -z |
tr '\0' '\n'
Which would give something like:
2020-02-08Z19:17:22.3588966190/Scripts/.distfiles
2020-02-09Z09:25:37.5336986350/StartupFiles/zshrc
2020-07-26Z20:33:17.7263164070/Misc/vcs_info-examples
2020-07-26Z20:33:17.7463157170/Util/ztst-syntax.vim
2020-08-22Z18:06:17.9773156630/Functions/VCS_Info
2020-08-30Z11:11:00.5701005930/autom4te.cache/requests
2020-08-30Z11:11:31.5245491550/Config/defs.mk
2020-08-30Z11:11:31.6085449480/Etc/Makefile
2020-08-30Z11:12:10.9305773600/INSTALL.d/share/zsh/5.8.0.2-dev/help
2020-10-22Z05:17:15.3808945480/Completion/Base/Utility
2020-10-22Z05:17:15.3928938520/Doc/Zsh/zle.yo
2020-10-22Z05:17:15.3968936190/Src/zsh.h
2020-10-22Z05:17:15.3968936190/Test/D02glob.ztst
2020-10-22Z05:17:15.4168924590/.git/logs/refs/heads/master
That is, giving the newest regular file in each directory with its timestamp. Directories without regular files in them are not shown.
To only see the list of directories, insert a cut -zd/ -f2 |
before the tr
command.
For a prettier output like in the zsh approach, you could replace the tr
command with:
LC_ALL=C gawk -v RS='\0' -F / '{
dir = $2; mtime = $1
sub("[^/]*/[^/]*/", "")
printf "%-20s %s (%s)\n", dir, mtime, $0}'
While we're at using gawk
, we could also tell find
to print the timestamp as a fractional Unix epoch time and gawk
reformat it in local time:
find . -mindepth 2 -type f -printf '%T@/%P\0' |
LC_ALL=C sort -zt/ -k2,2 -k1,1rn |
LC_ALL=C sort -t/ -zmsuk2,2 |
LC_ALL=C sort -zn |
LC_ALL=C gawk -v RS='\0' -F / '{
dir = $2; split($1, mtime, ".")
sub("[^/]*/", "")
printf "%-20s %s (%s)\n", dir, strftime("%FT%T." mtime[2] "%z", mtime[1]), $0}'
Which would give an output like:
cross-build 2019-12-02T13:48:33.0505299150+0000 (cross-build/x86-beos.cache)
m4 2019-12-02T13:48:33.4615093990+0000 (m4/xsize.m4)
autom4te.cache 2019-12-02T13:50:48.8897482560+0000 (autom4te.cache/requests)
CWRU 2020-08-09T17:17:21.4712835520+0100 (CWRU/CWRU.chlog)
include 2020-08-09T17:17:21.5872807740+0100 (include/posixtime.h)
tests 2020-08-09T17:17:21.8392747400+0100 (tests/type.right)
.git 2020-08-09T17:17:21.8472745490+0100 (.git/index)
doc 2020-08-09T17:35:35.1638603570+0100 (doc/Makefile)
po 2020-08-09T17:35:35.3758514290+0100 (po/Makefile)
support 2020-08-09T17:35:36.7037954930+0100 (support/man2html)
lib 2020-08-09T17:35:42.3755564970+0100 (lib/readline/libhistory.a)
builtins 2020-08-09T17:35:42.5035511020+0100 (builtins/libbuiltins.a)
examples 2020-08-09T17:35:47.1513551370+0100 (examples/loadables/cut)
INSTALL.d 2020-08-09T17:35:47.3993446790+0100 (INSTALL.d/lib/bash/cut)
In zsh
, you could define a by_age_of_newest_file
sort order function like:
zmodload zsh/stat
typeset -A newest_mtime newest_file
by_age_of_newest_file() {
local dir=${1-$REPLY}
local newest=($dir/**/*(ND.om[1]))
if (($#newest)); then
stat -gLA REPLY -F %FZ%T.%N +mtime -- $newest
newest_mtime[$dir]=$REPLY newest_file[$dir]=$newest
else
REPLY= newest_mtime[$dir]= newest_file[$dir]=
fi
}
Which you could use as:
print -rC1 -- *(ND/o+by_age_of_newest_file)
to print the list from oldest to newest (dirs with no file listed first). Replace o+
with O+
to reverse the order.
Or to print the directories alongside the newest file and its timestamp:
data=()
for dir (*(ND/o+by_age_of_newest_file))
data+=("$dir" "$newest_mtime[$dir]" "($newest_file[$dir])")
print -raC3 -- "$data[@]"
Which gives something like:
Scripts 2020-02-08Z19:17:22.358896619 (Scripts/.distfiles)
StartupFiles 2020-02-09Z09:25:37.533698635 (StartupFiles/zshrc)
Misc 2020-07-26Z20:33:17.726316407 (Misc/vcs_info-examples)
Util 2020-07-26Z20:33:17.746315717 (Util/ztst-syntax.vim)
Functions 2020-08-22Z18:06:17.977315663 (Functions/VCS_Info/Backends/VCS_INFO_get_data_hg)
autom4te.cache 2020-08-30Z11:11:00.570100593 (autom4te.cache/requests)
Config 2020-08-30Z11:11:31.524549155 (Config/defs.mk)
Etc 2020-08-30Z11:11:31.608544948 (Etc/Makefile)
INSTALL.d 2020-08-30Z11:12:10.870580360 (INSTALL.d/share/zsh/5.8.0.2-dev/help/zstyle)
Completion 2020-10-22Z05:17:15.380894548 (Completion/Base/Utility/_store_cache)
Doc 2020-10-22Z05:17:15.392893852 (Doc/Zsh/zle.yo)
Src 2020-10-22Z05:17:15.396893619 (Src/zsh.h)
Test 2020-10-22Z05:17:15.396893619 (Test/D02glob.ztst)
.git 2020-10-22Z05:17:15.416892459 (.git/logs/refs/heads/master)
(note the timestamps are in Zulu/UTC time)