【问题标题】:find the latest modified file and exec找到最新修改的文​​件并执行
【发布时间】:2016-11-29 00:56:46
【问题描述】:

我想在一个目录中找出最新构建的 rpm,然后在上面执行一些东西。类似于下面的东西。

/bin/ls -1t srcdir/*.rpm | head -1 

但是使用 find 命令

find srcdir/*.rpm <get-only-the-most-recently-modified-file> -exec "<do-something>"

【问题讨论】:

  • 既然您的问题涉及改进已经工作的代码,那它不是更适合Code Review Stack Exchange吗?
  • 实际上,我需要做的不仅仅是cp。我已经修改了问题。
  • 实际上,@CharlesDuffy 的解决方案都没有为您提供最新构建的 rpm,也许您想要最新修改的文​​件(请记住甚至 touch file 修改访问时间),如标题中正确提及并由他的解决方案。
  • 是的,我认为我可以安全地假设最新的 rpm 是最后修改的文件(在我的情况下)
  • 如果构建失败并且没有人会去touch rpm 文件,我会提前停止。

标签: bash shell find


【解决方案1】:

如果您只想查看最新的 rpm:

ls -1tr /pat/to/directory/*.rpm | tail -n 1

很好。但是由于[ ls output shouldn't be parsed ],如果您打算将文件用于某些目的,您需要向find寻求补救措施。

我的解决方案是:

#!/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

问题具体解决方案

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"

【讨论】:

  • 如果你有 GNU find,为什么不让它为你提取时间呢?比每个文件调用stat 便宜得多。
  • ...值得注意的是,这取决于 GNU stat; --printf 没有标准化。 (我的回答也不符合 POSIX 标准——对于完全可移植的解决方案,我们的方法都不起作用)。
  • ...实际上,我已经修改了我的答案,使其拥有一个不依赖于 bash 内置工具的解决方案。
  • @CharlesDuffy:谢谢,在重新阅读问题时,latest built rpm in a directory 引起了我的注意。该操作可能正在寻找文件出生时间,我可以使用stat --printf=%W 但这取决于文件系统并且不是很可靠。我刚看到你的更新,很棒的东西
  • 嗯。实际上,如果您想要实际的构建时间而不是本地 mtime,那可能是 rpm -Q --format=... -f "$filename" 调用。
【解决方案2】:

两种方法 - 一种可移植到非 GNU 平台,另一种快速使用大目录(在文件系统允许的范围内):


便携

什么?

BashFAQ #3: How can I sort or compare files based on some metadata attribute (newest / oldest modification time, size, etc)? 与此处相关。总结一下:

latest=
for f in "$srcdir"/*.rpm; do
  [ "$f" -nt "$latest" ] && latest=$f
done

如何?

[ "$a" -nt "$b" ] 检查变量 a 中命名的文件是否比 ksh 派生的 shell 中变量 b 中命名的文件新。


快速

...需要明确的是,对于非常大的目录,这会更快,而不是在所有情况下都更快。也就是说,它也很容易适应(例如)查找(例如)最新的 5 或 10 个文件,或除了最新的 5 或 10 个文件之外的所有文件,而其他方法几乎无法有效地做到这一点。 p>

什么?

如果您有 GNU 工具(GNU 查找、GNU 排序),请考虑以下事项:

{ read -r -d ' ' mtime && IFS= read -r -d '' filename; } \
  < <(find /directory -type f -iname "*.rpm" -printf '%T@ %p\0' | sort -z -r -n)

这会将您最新文件的时间(以秒为单位)放入 shell 变量 mtime 中,并将该文件的名称放入 filename 中。因此,您可以对该文件进行操作:

if [[ -e $filename ]]; then
  # do whatever arbitrary operations you're looking for on that resulting filename
  cp -- "$filename" /path/to/where/to/copy
fi

如何?

解释这是如何工作的:

find ... -printf '%T@ %p\0'

...以&lt;epoch_mtime&gt; &lt;filename&gt;&lt;NUL&gt; 格式发出内容,其中epoch_mtime 是自1970 年1 月1 日以来的秒数。

sort -z -r -n

...然后根据开头的数字对该输出进行排序,期望它是 NUL 分隔的。

{ read -r -d ' ' mtime && IFS= read -r -d '' filename; }

...将内容读入mtime 变量直到第一行的第一个空格,然后将第一个NUL 向前读入filename 变量。

【讨论】:

  • 好东西!谢谢。
猜你喜欢
  • 2011-06-14
  • 2012-06-12
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
  • 2014-07-24
  • 2011-06-16
  • 2014-10-28
相关资源
最近更新 更多