问题
I want to find out the latest built rpm in a directory and then exec something on it. Something similar to below.
/bin/ls -1t srcdir/*.rpm | head -1
But with the find command
find srcdir/*.rpm <get-only-the-most-recently-modified-file> -exec "<do-something>"
回答1:
Two approaches -- one portable to non-GNU platforms, the other fast with large directories (to the extent allowed by the filesystem):
Portable
What?
BashFAQ #3: How can I sort or compare files based on some metadata attribute (newest / oldest modification time, size, etc)? is relevant here. To summarize:
latest=
for f in "$srcdir"/*.rpm; do
[ "$f" -nt "$latest" ] && latest=$f
done
How?
[ "$a" -nt "$b" ] checks whether the file named in variable a is newer than that named in variable b in ksh-derived shells.
Fast
...to be clear, this is faster with very large directories, as opposed to faster in all cases. That said, it's also easily adapted to find (for instance) the 5 or 10 newest files, or all files except those 5 or 10 newest, which the other approach could not do nearly as effectively.
What?
If you have GNU tools (GNU find, GNU sort), consider the following:
{ read -r -d ' ' mtime && IFS= read -r -d '' filename; } \
< <(find /directory -type f -iname "*.rpm" -printf '%T@ %p\0' | sort -z -r -n)
This will put your latest file's time (in seconds-since-epoch) in the shell variable mtime and the name of that file in filename. Thus, you can then operate on that file:
if [[ -e $filename ]]; then
# do whatever arbitrary operations you're looking for on that resulting filename
cp -- "$filename" /path/to/where/to/copy
fi
How?
To explain how this works:
find ... -printf '%T@ %p\0'
...emits contents in the format <epoch_mtime> <filename><NUL>, where epoch_mtime is the number of seconds since January 1st, 1970.
sort -z -r -n
...then sorts that output, expecting it to be NUL-delimited, on the numbers at the beginning.
{ read -r -d ' ' mtime && IFS= read -r -d '' filename; }
...reads content into the mtime variable up to the first space in the first line, and then reads forward to the first NUL into the filename variable.
回答2:
If you just wish to see the latest rpm :
ls -1tr /pat/to/directory/*.rpm | tail -n 1
is good. But since [ ls output shouldn't be parsed ], you need to look to find for a remedy if you plan to use the file for some purpose as is in your case.
My Solution would be :
#!/bin/bash
declare -i lts # latest time stamp
declare -i cts # current time stamp
declare latestrpmfile="No file available"
lts=0
while read -r -d '' fname
do
cts="$( stat --printf=%Y "$fname" )"
if [ "$cts" -gt "$lts" ]
then
lts="$cts"
latestrpmfile="$fname"
fi
done < <( find /directory/to/rpm/files/ -type f -iname "*.rpm" -print0 )
#At this point $latestrpmfile will contain the full path to the
#latest rpm file
#Now, say, to copy the latest rpm file to a directory, do
if [ -e "$latestrpmfile" ]
then
cp "$latestrpmfile" /path/to/where/to/copy/
fi
Problem specific solution
lbt=0 #latest build time
lb="nosuchfile" #latest build
for i in "$srcdir"/*.rpm # source dir could be an argument to script
do
bt=$(rpm -q --queryformat "%{BUILDTIME}" -p "$i" 2>/dev/null)
if [ "$bt" -gt "$lbt" ]
then
lbt=$bt
lb="$i"
fi
done
#Do something with "$lb"
来源:https://stackoverflow.com/questions/38571882/find-the-latest-modified-file-and-exec