使用多个命令查找-exec

And*_*ndy 397 bash find

我试图使用find -exec与多个命令没有任何成功.有人知道以下命令是否可行?

find *.txt -exec echo "$(tail -1 '{}'),$(ls '{}')" \;
Run Code Online (Sandbox Code Playgroud)

基本上,我试图在当前目录中打印每个txt文件的最后一行,并在行的末尾打印,后跟文件名的逗号.

小智 598

find接受-exec命令的多个部分.例如:

find . -name "*.txt" -exec echo {} \; -exec grep banana {} \;
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下,第二个命令仅在第一个命令成功返回时运行,如@Caleb所述.如果您希望两个命令都运行而不管它们是成功还是失败,您可以使用以下构造:

find . -name "*.txt" \( -exec echo {} \; -o -exec true \; \) -exec grep banana {} \;
Run Code Online (Sandbox Code Playgroud)

  • @rajeev第二个exec仅在第一个返回代码返回成功时才会运行,否则将被跳过.这应该在这个答案中注明. (46认同)

小智 88

find . -type d -exec sh -c "echo -n {}; echo -n ' x '; echo {}" \;
Run Code Online (Sandbox Code Playgroud)

  • 永远不要在shell代码中嵌入`{}`.请参阅https://unix.stackexchange.com/questions/156008/is-it-possible-to-use-find-exec-sh-c-safely (6认同)
  • 如果你想运行Bash而不是Bourne,你也可以使用`... -exec bash -c ...`而不是`... -exec sh -c ...`. (3认同)
  • +1 @Kusalananda注入文件名是脆弱和不安全的.使用参数.见[SC2156](https://github.com/koalaman/shellcheck/wiki/SC2156) (3认同)

Pau*_*ce. 48

以下之一:

find *.txt -exec awk 'END {print $0 "," FILENAME}' {} \;

find *.txt -exec sh -c 'echo "$(tail -n 1 "$1"),$1"' _ {} \;

find *.txt -exec sh -c 'echo "$(sed -n "\$p" "$1"),$1"' _ {} \;
Run Code Online (Sandbox Code Playgroud)

  • {}之前的下划线是什么? (12认同)
  • 对于这种方法,传递给`sh -c`的脚本是单引号而不是双引号是至关重要的.否则`$ 1`的范围是错误的. (3认同)
  • @Nick 引号与它无关 - 只要您对变量 (`"\$1"`) 进行转义,您就可以用双引号编写 `'$1'`。您也可以转义其他字符(`"\""`)。 (3认同)
  • @qed:它是一个丢弃值,保留了$ 0的位置.尝试使用"foobar"而不是"_":`find/usr/bin -name find -exec sh -c'echo"[$ 0] [$ 1]"'foobar {} \;` - 输出:"[foobar ] [/ usr/bin/find]". (2认同)

小智 16

另一种方式是这样的:

multiple_cmd() { 
    tail -n1 $1; 
    ls $1 
}; 
export -f multiple_cmd; 
find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)

在一条线上

multiple_cmd() { tail -1 $1; ls $1 }; export -f multiple_cmd; find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)
  • " multiple_cmd()" - 是一个功能
  • " export -f multiple_cmd" - 将导出它,以便任何其他子shell可以看到它
  • " find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;" - 找到将在您的示例中执行该功能

通过这种方式,multiple_cmd可以根据需要同样长且复杂.

希望这可以帮助.


Cam*_*tin 10

有一种更简单的方法:

find ... | while read -r file; do
    echo "look at my $file, my $file is amazing";
done
Run Code Online (Sandbox Code Playgroud)

或者:

while read -r file; do
    echo "look at my $file, my $file is amazing";
done <<< "$(find ...)"
Run Code Online (Sandbox Code Playgroud)

  • 文件名中可以​​包含换行符,这就是为什么 find 具有 -print0 参数而 xargs 具有 -0 参数 (3认同)
  • @abasterfield 我一直希望永远不要在野外找到那些,哈哈 (2认同)
  • 我想做的是“find ... -exec zcat {} | wc -l \;” 这不起作用。然而,发现... | 当读取-r文件时;执行 echo "$file: `zcat $file | wc -l`"; 完成确实有效,所以谢谢! (2认同)

use*_*932 8

扩展@Tinker 的回答,

就我而言,我需要做一个command | command | command内部的-exec同时打印文件名,并在含有一定的文本文件找到的文本。

我能够做到:

find . -name config -type f \( -exec  grep "bitbucket" {} \; -a -exec echo {} \;  \) 
Run Code Online (Sandbox Code Playgroud)

结果是:

    url = git@bitbucket.org:a/a.git
./a/.git/config
    url = git@bitbucket.org:b/b.git
./b/.git/config
    url = git@bitbucket.org:c/c.git
./c/.git/config
Run Code Online (Sandbox Code Playgroud)

  • 您还可以通过将 `/dev/null` 作为第二个参数传递给带有一个 `-exec` 参数的 `grep` 命令,在一行上打印文件名和 grep 内容:```find 。-name config -type f -exec grep "bitbucket" {} /dev/null \;``` (3认同)

And*_*ini 7

我不知道你是否可以使用find来做到这一点,但另一种解决方案是创建一个shell脚本并使用find运行它.

lastline.sh:

echo $(tail -1 $1),$1
Run Code Online (Sandbox Code Playgroud)

使脚本可执行

chmod +x lastline.sh
Run Code Online (Sandbox Code Playgroud)

用途find:

find . -name "*.txt" -exec ./lastline.sh {} \;
Run Code Online (Sandbox Code Playgroud)

  • 不推荐使用反引号,请鼓励使用更好的可读性,字体独立且易于嵌套的$(...).谢谢. (7认同)

Gre*_*rty 6

感谢 Camilo Martin,我能够回答一个相关的问题:

我想做的是

find ... -exec zcat {} | wc -l \;
Run Code Online (Sandbox Code Playgroud)

这不起作用。然而,

find ... | while read -r file; do echo "$file: `zcat $file | wc -l`"; done
Run Code Online (Sandbox Code Playgroud)

确实有效,谢谢!


Eri*_*eau 5

丹尼斯的第一个答案是解决问题的答案。但事实上,它不再是像标题所暗示的那样,在一个 exec 中找到多个命令。要回答一个执行多个命令的问题,我们将不得不寻找其他解决方案。这是一个例子:

使用多个 {} 引用使用 1 个 exec 命令保留过去 7 天内修改过的最后 10000 行 .log 文件

1) 查看命令将对哪些文件执行什么操作:

find / -name "*.log" -a -type f -a -mtime -7 -exec sh -c "echo tail -10000 {} \> fictmp; echo cat fictmp \> {} " \;
Run Code Online (Sandbox Code Playgroud)

2)这样做:(注意不再需要“\>”,而只需要“>”)

find / -name "*.log" -a -type f -a -mtime -7 -exec sh -c "tail -10000 {} > fictmp; cat fictmp > {} ; rm fictmp" \;