我想找到目录列表,然后在其中搜索给定文件,然后选择最新的文件。
这就是我尝试的:
find /Temp -type d -name Ast 2>/dev/null | while read Dir; do find $Dir -type f -name Pagination.json 2>/dev/null -exec ls -lt {} +; done
这确实给我带来了预期的文件,但它按升序对它们进行排序。
这是该命令的结果:
-rw-r--r-- 1 root root 46667 Sep 12 18:10 /Temp/ProjectOne/Site/Ast/BaseComponents/Pagination.json
-rw-r--r-- 1 root root 46667 Sep 13 09:31 /Temp/ProjectTwo/Site/Ast/BaseComponents/Pagination.json
在这种情况下,我需要第二项。我应该怎么办?
答案1
我解决这个问题的方法是使用 shell 自己的文件查找功能来查找所有候选者,然后保留最新的:
#!/bin/bash
# enable ** as recursive glob, don't fail when null matches are found, and
# also look into things starting with .
shopt -s globstar nullglob dotglob
newestmod=0
for candidate in **/Ast/**/Pagination.json ; do
# check file type:
[[ -f ${candidate} ]] || continue
[[ -L ${candidate} ]] && continue
# Get modification time in seconds since epoch without fractional
# part. Assumes GNU stat or compatible.
thisdate=$(stat -c '%Y' -- "${candidate}")
# if older than the newest found, skip
[[ ${thisdate} -lt ${newestmod} ]] && continue
newestmod=${thisdate}
newestfile="${candidate}"
done
if (( newestmod )); then
printf 'Newest file: "%s"\n' "${newestfile}"
fi
或诸如此类。
在 中zsh
,整个事情变得不那么复杂,并且支持时间戳的亚秒精度:
#!/usr/bin/zsh
#get the list of regular (`.`) files, `o`rdered by `m`odification date
allcandidates=(**/Ast/**/Pagination.json(ND.om))
if (( $#allcondidates )) print -r Newest file: $allcandidates[1]
要不就:
print -r Newest file: **/Ast/**/Pagination.json(D.om[1])
请注意,虽然**/
在 zsh 和 bash5.0+ 中,递归遍历目录树时不遵循符号链接,但该Ast/
部分将遍历符号链接。如果这是一个问题,在 中zsh
,您可以通过以下方式解决它:
set -o extendedglob
print -r Newest file: ./**/Pagination.json~^*/Ast/*(D.om[1])
where./**/Pagination.json
查找所有文件而不遍历符号链接,但~pattern
删除与模式匹配的路径,这里是不 ( ^
) 包含/Ast/
.
答案2
它会根据您所说的“最新”的确切含义而略有变化,但是只要 GNU 实现find
可用,并且如果我们知道不存在包含换行符的文件路径,我会使用类似以下内容的内容:
find /tmp -type f -printf "%T@ %p\n" | sort -rn
(调整/tmp -type f
以找到您真正关心的文件,它可能会类似于find /Temp -path '*/Ast/*' -type f -name 'Pagination.json'
)。有趣的部分是%T@
打印文件自纪元以来的最后修改时间(以秒为单位),这很容易排序。