How to sort results of Find statement by date?
get file names only ... sorted by modification day
find
+ sort
+ cut
approach:
find . -regex ".*/[0-9.]+" -printf "%T@ %f\n" | sort | cut -d' ' -f2
%T@
- File's last modification time, where@
is seconds sinceJan. 1, 1970, 00:00 GMT,
with fractional part%f
- File's name with any leading directories removed (only the last element)
To sort in descending order:
find . -regex ".*/[0-9.]+" -printf "%T@ %f\n" | sort -k1,1r | cut -d' ' -f2
Your method can be adapted to work in simple cases. The main problem you're facing is that you're passing input to ls
, but ls
doesn't take any input. ls
takes command line arguments. So you need to pass the output of find
as arguments to ls
, with a command substitution. Also, in case a directory is matched, pass -d
to ls
to list the directory itself and not its contents.
OLDDATA=$(ls -td $(find . -regex ".*/[0-9.]+"))
Only in simple cases, because there are two restrictions:
- This relies on an unquoted command substitution (and so does the use of
$OLDDATA
afterwards). Therefore it assumes that the file names don't contain any special characters (whitespace or wildcard characters\[*?
). - Some versions of
ls
may mangle characters that are not printable in the current locale. - If the total length of the file names is too long, you'll get an error. (Note that
find … -exec
andxargs
cannot help here, sincels
must run a single time to get the order of the file names right. All they could do is hide errors and produce output that is not correctly sorted — and mangle a few more characters, in the case ofxargs
.)
A robust, simple way of doing this is to use zsh. It has the ability to sort wildcard matches, thanks to glob qualifiers.
setopt extended_glob
OLDDATA=(**/[0-9.]##(om))
- Since this doesn't call any other program, there is no length limit other than available memory, and no risk of file name mangling at any point.
- The result is a list of strings (each string being a file name), not a string, so it goes into an array variable.
**/
traverses subdirectories recursively, avoiding the use offind
.##
means “one or more of the preceding” in zsh extended glob syntax, it's analogous to+
in (extended) regex syntax.(om)
is a glob qualifier to sort files by modification time, likels -t
.
There is notoriously no simple way to do this robustly with POSIX tools or even with GNU tools and ksh.