How to list files sorted by modification date recursively (no stat command available!)
My shortest method uses zsh:
print -rl -- **/*(.Om)
(add the D
glob qualifiers if you also want to list the hidden files or the files in hidden directories).
If you have GNU find, make it print the file modification times and sort by that. I assume there are no newlines in file names.
find . -type f -printf '%T@ %p\n' | sort -k 1 -n | sed 's/^[^ ]* //'
If you have Perl (again, assuming no newlines in file names):
find . -type f -print |
perl -l -ne '
$_{$_} = -M; # store file age (mtime - now)
END {
$,="\n";
print sort {$_{$b} <=> $_{$a}} keys %_; # print by decreasing age
}'
If you have Python (again, assuming no newlines in file names):
find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'
If you have SSH access to that server, mount the directory over sshfs on a better-equipped machine:
mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt
With only POSIX tools, it's a lot more complicated, because there's no good way to find the modification time of a file. The only standard way to retrieve a file's times is ls
, and the output format is locale-dependent and hard to parse.
If you can write to the files, and you only care about regular files, and there are no newlines in file names, here's a horrible kludge: create hard links to all the files in a single directory, and sort them by modification time.
set -ef # disable globbing
IFS='
' # split $(foo) only at newlines
set -- $(find . -type f) # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do # hard link the files to links.tmp/0, links.tmp/1, …
ln "../$f" $i
i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do # for each file, in reverse mtime order:
eval 'list="${'$i'} # prepend the file name to $list
$list"'
done
printf %s "$list" # print the output
rm -f [0-9]* # clean up
cd ..
rmdir links.tmp
Assuming GNU find
:
find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-
Change 1n,1
to 1nr,1
if you want the files listed most recent first.
If you don't have GNU find
it becomes more difficult because ls
's timestamp format varies so much (recently modified files have a different style of timestamp, for example).
On a mac there is no -printf argument to find, but you can do this instead:
find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'