我有一个试图为文件生成UUID的命令:
find -printf "%P\n"|sort|xargs -L 1 echo $(uuid)
Run Code Online (Sandbox Code Playgroud)
但在结果中,xargs只执行$(uuid)一次子shell:
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file1
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file2
8aa9e7cc-d3b2-11e4-83a6-1ff1acc22a7e file3
Run Code Online (Sandbox Code Playgroud)
是否有一个单行(即不是函数)xargs来执行每个输入的子shell命令?
hek*_*mgl 17
这是因为$(uuid)在当前shell中扩展了.您可以显式调用shell:
find -printf "%P\n"| sort | xargs -I '{}' bash -c 'echo $(uuid) {}'
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我会使用以下命令:
find -exec bash -c 'echo "$(uuid) ${1#./}"' -- '{}' \;
Run Code Online (Sandbox Code Playgroud)
没有xargs.
hek2mgl的回答很好地解释了问题,并且他的解决方案效果很好;这个答案着眼于性能。
\n\n接受的答案有点慢,因为它bash为每个输入行创建一个过程。
虽然xargs通常比 shell 代码循环更可取并且更快,但在这种特殊情况下,角色相反,因为每次迭代都需要 shell 功能。
以下替代解决方案使用while循环来处理输入行,在我的机器上,速度大约是该解决方案的两倍xargs。
find . -printf "%P\\n" | sort | while IFS= read -r f; do echo "$(uuid) $f"; done\nRun Code Online (Sandbox Code Playgroud)\n\nwhile而不是for,因为for无法稳健地解析命令输出(简而言之:带有嵌入空格的文件名会破坏命令 - 请参阅http://mywiki.wooledge.org/DontReadLinesWithFor)。如果您担心带有嵌入换行符的文件名(非常罕见)并使用GNU实用程序,则可以使用 NUL 字节作为分隔符:
\n\nfind . -printf "%P\\0" | sort -z | while IFS= read -d \'\' -r f; do echo "$(uuid) $f"; done\nRun Code Online (Sandbox Code Playgroud)\n\n更新:最快的方法是根本不使用 shell 循环,如\xe1\xb4\xb3\xe1\xb5\x81\xe1\xb4\xb5\xe1\xb4\xb0\xe1\xb4\xbc\'所示聪明的答案。\n请参阅下面的答案的便携式版本。
\n\n兼容性说明:
\n\nOP的find命令暗示使用GNU find(Linux),并使用特性(-printf可能无法在其他平台上工作的功能 ( )。
这是\xe1\xb4\xb3\xe1\xb5\x81\xe1\xb4\xb5\xe1\xb4\xb0\xe1\xb4\xbc\ 的答案的便携式版本,仅使用find(和awk)。
\n但请注意,这uuid不是 POSIX 实用程序;它是一个实用程序。由于 Linux 和类似 BSD 的系统(包括 OSX)有一个uuidgen实用程序,因此该命令使用它:
find . -exec printf \'%s\\t\' {} \\; -exec uuidgen \\; | \n awk -F \'\\t\' \'{ sub(/.+\\//,"", $1); print $2, $1 }\' | sort -k2\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
7830 次 |
| 最近记录: |