如何将 find 的输出通过管道传输到另一个 find 中

如何将 find 的输出通过管道传输到另一个 find 中

在搜索如何find根据修改时间对找到的文件进行排序时,我发现这个答案它提供了以下咒语:

find . -type f -printf '%T@ %p\n' | sort -k 1nr | sed 's/^[^ ]* //' | head -n 10

上面的问题是我无法记住它,也无法找到一种方法将其打包为 shell 脚本,以便我可以通过自己的调用来提供它,find我可以选择应用任何参数我想。例如,如何将上述内容打包为 shell 脚本“”的形式,showLatest以便我可以执行以下操作?

find src -type f -iname \*.py | showLatest 10

答案1

在 zsh 中,showLatest 10位于(om[1,10])模式的末尾。这些都是全局限定符;om按修改时间排序(最年轻的在前)并[1,10]选择前 10 个匹配项。

find src -type f -iname \*.pyprint -lr src/**/(#i)*.py(D.)(您需要setopt extended_glob先运行,将其放入您的~/.zshrc)。

通配标志.仅过滤常规文件,D包括隐藏文件和隐藏目录中的文件,就像find版本一样。(#i)是一个通配标志这使得模式的其余部分不区分大小写。

print -lrprint -lr --打印其参数,每行一个(如果第一个参数可能以破折号开头,则打印该参数)。结合两者,获取最新的文件:

print -lr src/**/(#i)*.py(D.om[1,10])

在实践中您可以缩短为print -lr src/**/*.py(om[1,10]).

在 zsh 中,您可能不需要这个,因为您可以在获得文件列表时对其进行排序,至少如果它们都来自单一模式的话。这是在 zsh 中实现的一种方法showLatest,可以处理任意文件列表。不幸的是,omglob 限定符只能应用于单个模式,并且单个模式只能匹配单个目录或树中的文件。绕过此问题的技巧是使用e(或+) glob 限定符将任意列表注入到匹配结果中。然后应用oglob 限定符来执行排序;内置限定符不会作用于e/+重写的结果,但自定义限定符 (oeo+) 会作用(从 zsh 5.0.5 开始)。

#!/usr/bin/env zsh
zmodload zsh/stat
files=("${(@f)$(<&0)}")
print -lr .(e\''reply=($files)'\'noe\''stat -A REPLY +mtime -- $REPLY'\')

答案2

这个脚本对我有用:

#!/bin/bash
#
while IFS= read -r line; do
  find "$line" -printf '%T@ %p\n'
done | sort -k 1nr | sed 's/^[^ ]* //' | head -n 10

你可以通过它进行管道传输find

(0)asus-romano:~/tmp% find . -type f | ./script11.sh
./script11.sh
./script10.sh
[...]

zsh可以使用全局别名,这要快得多,但我认为bash没有它们:

(0)asus-romano:~/tmp% alias -g showlast10="-printf '%T@ %p\n' | sort -k 1nr | sed 's/^[^ ]* //' | head -n 10"
(0)asus-romano:~/tmp% find . -type f showlast10
./script11.sh
./script10.sh
./Just  tab.xyz
[...]

答案3

首先,当然可以编写类似的脚本showLatest,甚至可能find在其中使用。但这样每个文件都必须检查两次。

所以虽然这没有回答最后提出的问题,但应该解决首先描述的问题。即如何喂一个灵活的参数列表来查找。

sfind.sh:

#!/bin/bash
find "${@:1:$[$#-1]}" -printf '%T@ %p\n' | sort -k 1nr | sed 's/^[^ ]* //' | head -n ${@:$#:1}

一般的调用是sfind.sh [find-parameters] count.对于给定的例子,它将是sfind.sh src -type f -iname \*.py 10

解释:

  • $@包含传递给脚本的参数列表
  • $#是$@的长度
  • ${@:1:$[$#-1]}除最后一个参数外的所有参数
  • ${@:$#:1}最后一个参数

相关内容