Instead of parsing ls
, and if you can rely on the external stat
utility and bash v4+ (for associative arrays), you could gather the list of files by inode, then gather a list of the most recent inodes, then build an array of filenames:
shopt -s nocaseglob extglob
declare -a filesbyinode=()
for f in *.@(jpg|png); do filesbyinode[$(stat -c %i "$f")]=$f; done
[ ${#filesbyinode[@]} -gt 0 ] || return
declare wantedfiles=()
for inodes in $(stat -c '%Y %i' *.@(jpg|png) | sort -k1,1rn | awk '{print $2}' | head -10)
do
wantedfiles+=("${filesbyinode[$inodes]}")
done
declare -p wantedfiles
The first step is to set two shell options:
nocaseglob
-- this enables the wildcard jpg
to also match JPG
(and JpG
and ...)
extglob
-- this enables the use of @(jpg|png)
which means: matching filenames can end in either jpg
or png
(subject to nocaseglob
, above)
We then set up an empty associative array that indexes filenames by their inodes.
The subsequent for
loop builds up the filesbyinode
array with inode indexes (the result of the stat
command) and filenames as values.
If there are no files, we bail out with a return
-- adjust this as needed for your situation (perhaps an if/else).
We then declare a (regular) array to hold the files that we're interested in. The next for
loop iterates over the 10 most recent inodes and adds the corresponding filenames to the array. The 10 most recent inodes are determined by expanding the same wildcard as before, but asking only for the modification time (in seconds since the epoch) and the inodes; after sorting by the modification time in field #1 (largest/most recent first), we peel out the inodes in field #2 with awk
and grab the top 10 of those with head
.
As a demonstration that the code is safe for various filenames:
for i in $(seq 1 10); do touch $RANDOM.jpg $RANDOM.png $RANDOM.txt; sleep 1.1; done
touch x.jpg '[x].jpg' 'a?b.jpg' 'a*b.jpg' '$( echo boom ).jpg'
touch single\'quote.jpg double\"quote back\\slash.jpg '*.jpg' ②.jpg
... the output is:
declare -a wantedfiles=([0]="②.jpg" [1]="*.jpg" [2]="single'quote.jpg" [3]="back\\slash.jpg" [4]=$'X\240Y.jpg' [5]="[x].jpg" [6]="a?b.jpg" [7]="a*b.jpg" [8]="\$( echo boom ).jpg" [9]="25396.jpg")
(adjust the last filename for whatever $RANDOM
came up with).