在 find -exec 中使用 basename?

Wan*_*ang 6 find basename

如果我只使用 basename {} .txt,它会起作用:

find . -iname "*.txt" -exec basename {} .txt \;
Run Code Online (Sandbox Code Playgroud)

它只会打印 xxx 而不是 ./xxx.txt

如果我想在 -exec 选项中使用 $(basename {} .txt) ,它将失败:

find . -iname "*.txt" -exec echo "$(basename {} .txt)" \;
Run Code Online (Sandbox Code Playgroud)

它只会打印 ./xxx.txt

我怎么解决这个问题?我希望我可以$(basename {} .txt)用作其他 cmd 的参数。我必须用 xargs做sh -c或管道-exec basename {} \;吗?

cuo*_*glm 9

尝试:

find -iname "*.txt" -exec sh -c 'for f do basename -- "$f" .txt;done' sh {} +
Run Code Online (Sandbox Code Playgroud)

你的第一个命令失败了,因为$(...)在子shell中运行,它被{}视为文字。所以basename {} .txt返回{},你find变成了:

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

哪个打印文件名匹配。


小智 9

$()如果使用sh -cand 单引号,您仍然可以用于命令替换:

find . -iname "*.txt" -exec sh -c 'echo "$(basename {} .txt)"' \;
Run Code Online (Sandbox Code Playgroud)

单引号防止主 shell 执行内部的子命令,因此可以在命令替换为文件名$()执行它。请参阅Stack Overflow 上的这个答案以获得更全面的解释。sh -c find{}

请注意,您还可以在 内添加双引号$()来处理文件名中的空格:

find . -iname "*.txt" -exec sh -c 'echo "$(basename "{}" .txt)"' \;
Run Code Online (Sandbox Code Playgroud)


小智 6

相反,还有另一种使用 bash 管道和xargs命令的方法:

    find . -iname '*.txt' | xargs -L1 -I{} basename "{}"
Run Code Online (Sandbox Code Playgroud)

xargs上面的命令中:

参数表示逐行执行命令行-L1的输出。find

-I{}参数旨在find用双引号括起命令的输出,以避免 bash 分词(当文件名包含空格时)。