查找带有多个命令的-exec

我试图使用查找-exec与多个命令没有任何成功。有人知道像下面这样的命令是否可行吗?

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

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

415183 次浏览

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

lastline.sh:

echo $(tail -1 $1),$1

使脚本可执行

chmod +x lastline.sh

使用# EYZ0:

find . -name "*.txt" -exec ./lastline.sh {} \;

下列其中一项:

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"' _ {} \;

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

find . -name "*.txt" -exec echo {} \; -exec grep banana {} \;

注意,在这种情况下,只有当第一个命令成功返回时,第二个命令才会运行,正如@Caleb提到的那样。如果你想让两个命令都运行,不管它们成功或失败,你可以使用这个结构:

find . -name "*.txt" \( -exec echo {} \; -o -exec true \; \) -exec grep banana {} \;

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

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

1)看看这个命令会对哪些文件做什么:

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

2)这样做:(注意没有更多的“\>”,而只有“>”,这是需要的)

# EYZ0

find . -type d -exec sh -c "echo -n {}; echo -n ' x '; echo {}" \;

有一个更简单的方法:

find ... | while read -r file; do
echo "look at my $file, my $file is amazing";
done

另外:

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

应该使用xargs:)

find *.txt -type f -exec tail -1 {} \; | xargs -ICONSTANT echo $(pwd),CONSTANT

另一个(在osx上工作)

find *.txt -type f -exec echo ,$(PWD) {} + -exec tail -1 {} + | tr ' ' '/'

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

我想做的是

find ... -exec zcat {} | wc -l \;

但这并不奏效。然而,

find ... | while read -r file; do echo "$file: `zcat $file | wc -l`"; done

确实有用,所以谢谢!

另一种方法是这样的:

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

在一行中

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

通过这种方式,multiple_cmd可以根据您的需要任意长和复杂。

希望这能有所帮助。

一个find+xargs的答案。

下面的例子找到了所有.html文件,并创建了一个附加了.BAK扩展名的副本(例如1.html > 1.html.BAK)。

带有多个占位符的单个命令

find . -iname "*.html" -print0 | xargs -0 -I {} cp -- "{}" "{}.BAK"

具有多个占位符的多个命令

find . -iname "*.html" -print0 | xargs -0 -I {} echo "cp -- {} {}.BAK ; echo {} >> /tmp/log.txt" | sh


# if you need to do anything bash-specific then pipe to bash instead of sh

该命令也适用于以连字符开头或包含空格的文件,例如-my file.html(多亏了参数引用)和cp之后的--(向cp表示参数的结束和实际文件名的开始)。

-print0使用空字节终止符传递结果。


对于xargs-I {}参数将{}定义为占位符;你可以使用任何你喜欢的占位符;-0表示输入项是空分隔的。

扩展@Tinker的回答,

在我的例子中,我需要在-exec中创建command | command | command,以打印文件名和包含特定文本的文件中找到的文本。

我可以用:

find . -name config -type f \( -exec  grep "bitbucket" {} \; -a -exec echo {} \;  \)

结果是:

    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

我通常将find嵌入到一个小的for循环一行中,其中查找在带有$()的子命令中执行。

你的命令看起来像这样:

for f in $(find *.txt); do echo "$(tail -1 $f), $(ls $f)"; done

好的方面是,您可以使用{}而不是$f,而不是-exec …,您可以在do; done之间编写所有命令。

不知道你到底想做什么,但也许像这样?

for f in $(find *.txt); do echo $f; tail -1 $f; ls -l $f; echo; done

下面是我的bash脚本,您可以使用它来查找多个文件,然后使用一个命令处理它们。

用法示例。这个命令对每个找到的文件应用file linux命令:

./finder.sh file fb2 txt

仪脚本:

# Find files and process them using an external command.
# Usage:
#   ./finder.sh ./processing_script.sh txt fb2 fb2.zip doc docx


counter=0
find_results=()
for ext in "${@:2}"
do
# @see https://stackoverflow.com/a/54561526/10452175
readarray -d '' ext_results < <(find . -type f -name "*.${ext}" -print0)


for file in "${ext_results[@]}"
do
counter=$((counter+1))
find_results+=("${file}")
echo ${counter}") ${file}"
done
done
countOfResults=$((counter))
echo -e "Found ${countOfResults} files.\n"




echo "Processing..."
counter=0
for file in "${find_results[@]}"
do
counter=$((counter+1))
echo -n ${counter}"/${countOfResults}) "
eval "$1 '${file}'"
done
echo "All files have been processed."


我找到了这个解决方案(可能已经在评论中说过了,但我找不到任何答案)

你可以在一行中使用&;bash -c"

find . <SOMETHING> -exec bash -c "EXECUTE 1 && EXECUTE 2 ; EXECUTE 3" \;

在你的情况下

find . -name "*.txt" -exec bash -c "tail -1 '{}' && ls '{}'" \;

我用一个测试文件测试了它:

 [gek@tuffoserver tmp]$ ls *.txt




casualfile.txt
[gek@tuffoserver tmp]$ find . -name "*.txt" -exec bash -c "tail -1 '{}' && ls '{}'" \;
testonline1=some TEXT
./casualfile.txt