Display human readable timestamps.
🕒 🕑 🕐
find . -printf '%T@\t%p\n'|\
sort -nr -k1|\
awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'
This command lists all files and directories recursively and sorts the output such that most recently modified files and directories come first. For each output line, the modification timestamp is displayed in a human readable format. It uses find(1), sort(1) and awk(1) to efficiently accomplish this task.
Example:
$ find /tmp/tree -printf '%T@\t%p\n'|sort -nr -k1|awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'
2023-08-28 11:49 /tmp/tree/c
2023-08-28 11:46 /tmp/tree/d
2023-08-28 11:46 /tmp/tree
2023-08-25 11:49 /tmp/tree/c/1.txt
2023-07-29 11:51 /tmp/tree/a
2022-01-05 10:51 /tmp/tree/a/b/2.txt
2022-01-05 10:51 /tmp/tree/a/b/1.txt
2022-01-05 10:51 /tmp/tree/a/b
2018-03-07 10:50 /tmp/tree/c/2.txt
2015-06-11 11:50 /tmp/tree/c/3.txt
Command pipeline break down and explanation
The find command lists all files and directories for the provided path in file system order and invokes the printf
action for each path. The format string specifies that the first column should be the path modification time as a number %T@
, and the second column should be the path itself %p
.
$ find /tmp/tree -printf '%T@\t%p\n'1693215986.8473050140 /tmp/tree
1693216167.2705184680 /tmp/tree/c
1434016210.0000000000 /tmp/tree/c/3.txt
1520416204.0000000000 /tmp/tree/c/2.txt
1692956994.0000000000 /tmp/tree/c/1.txt
1690624265.0000000000 /tmp/tree/a
1641376305.0000000000 /tmp/tree/a/b
1641376313.0000000000 /tmp/tree/a/b/2.txt
1641376313.0000000000 /tmp/tree/a/b/1.txt
1693215986.8473050140 /tmp/tree/d
|
The sort command reads lines from standard input and sorts them using the first column as sorting key and interpreting those values numerically. It outputs the sorted lines in descending/reverse order:
$ ...|sort -nr -k1
1693216167.2705184680 /tmp/tree/c
1693215986.8473050140 /tmp/tree/d
1693215986.8473050140 /tmp/tree
1692956994.0000000000 /tmp/tree/c/1.txt
1690624265.0000000000 /tmp/tree/a
1641376313.0000000000 /tmp/tree/a/b/2.txt
1641376313.0000000000 /tmp/tree/a/b/1.txt
1641376305.0000000000 /tmp/tree/a/b
1520416204.0000000000 /tmp/tree/c/2.txt
1434016210.0000000000 /tmp/tree/c/3.txt
-n | numeric interpretation of the values used for sorting lines |
-r | descending/reversed order |
-k1 | sorting key, use first column of each line as the sorting value |
|
The awk command transforms the lines so that timestamps are presented in a human readable form.
$ ...|awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'
2023-08-28 11:49 /tmp/tree/c
2023-08-28 11:46 /tmp/tree/d
2023-08-28 11:46 /tmp/tree
2023-08-25 11:49 /tmp/tree/c/1.txt
2023-07-29 11:51 /tmp/tree/a
2022-01-05 10:51 /tmp/tree/a/b/2.txt
2022-01-05 10:51 /tmp/tree/a/b/1.txt
2022-01-05 10:51 /tmp/tree/a/b
2018-03-07 10:50 /tmp/tree/c/2.txt
2015-06-11 11:50 /tmp/tree/c/3.txt
-F\\t | tell awk to use the tab character as field separator, used to split each input line into columns |
{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2} | the awk program itself; for each line, print() a formatted timestamp by parsing the first column using strftime (), a tab character, then the path from the second column unchanged, forming a line of output. (In awk syntax, values presented in sequence are concatenated, so the print function only receives one string argument.) |
Variations
List oldest first
By simply removing the -r
option to sort
, we get ascending order, e.g. from older to newer timestamps:
find /tmp/tree -printf '%T@\t%p\n'|\
sort -n -k1|\
awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'
Limit number of lines output
By adding head(1) to the pipeline we can limit output to any desirable number:
find /tmp/tree -printf '%T@\t%p\n'|\
sort -nr -k1|\
awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'|\
head -n 10
List only files
By adding -type f
predicate to the find
command, we can exclude all directories from the output:
find /tmp/tree -type f -printf '%T@\t%p\n'|\
sort -nr -k1|\
awk -F\\t '{print strftime("%Y-%m-%d %H:%M",$1) "\t" $2}'
(Or vice versa, we can use -type d
to include only directories.)
Find single most recently modified path under each top level directory
This one is more specialized and lists for each top level directory only the single most recently modified sub-path, sorted by modification time:
find /tmp/tree -mindepth 2 -printf '%T@\t%P\n'|\
sort -nr -k1|\
awk -F\\t '
{
topdir=$2;
gsub(/\/.*/, "", topdir);
if (topdir=="") { topdir="." };
if (!seen[topdir]) {
seen[topdir]=1;
print strftime("%Y-%m-%d %H:%M",$1) "\t" $2;
}
}'
This might be useful to get an indication of which directory trees have recently been updated vs old trees that rarely see any file system writing activity. (The modification time of the top level directories themselves is often not a good indicator, since it does not reflect modifications deeper down in the tree.)
To accomplish this we tell find
to only print paths two or more levels below the search path root /tmp/tree
with -mindepth 2
and add a subtle change to the format pattern which strips the search path prefix: %P
. Also, we need to expand the awk
program so that it only prints the first path per encountered top level directory.
Example output:
2023-08-25 11:49 c/1.txt
2022-01-05 10:51 a/b/2.txt
So the most recently modified subtree is c/
, with most recently modified file c/1.txt
. (To include all files directly below the search path, you can change -mindepth
to 1.)