xargs如何将结果{}放入$(cmd {})?

时间:2014-07-12 20:35:52

标签: bash xargs

例如: find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|xargs -I{} echo "{} =>" $(realpath {}) 我想输出:

/usr/lib/libblas.so.3gf=>/usr/lib/libblas/libblas.so.3gf.0
/usr/lib/libblas.so=>/usr/lib/libblas/libblas.so.3gf.0
/usr/lib/libblas.a=>/usr/lib/libblas/libblas.a

这不起作用,因为$()中的值在脚本实际运行之前展开。

有什么办法可以达到这个效果吗?在bash中没有循环?

5 个答案:

答案 0 :(得分:4)

可替换地:

find /usr/lib -maxdepth 1 -type l \
  -exec echo -n '{} =>' \; \
  -exec realpath '{}' \;

答案 1 :(得分:1)

让xargs调用shell:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|xargs -I{} sh -c 'echo "{} =>" $(realpath {})'

答案 2 :(得分:1)

您需要在知道文件名后进行命令替换。所以你需要xargs来调用shell并在那里进行替换。

由于您一次在单个文件上运行命令,因此使用xargs是一种无用的复杂功能(并且它还会破坏某些文件名)。使用-exec

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'echo "$0 => $(realpath "$0")' {} \;

通过不使用命令替换,您可以使这一点稍快一点,而不是更清晰:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'echo -n "$0 => "; realpath "$0"' {} \;

为了让事情变得更快,不要为每个文件调用新的shell进程:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*" -exec sh -c 'for x; do echo -n "$x => "; realpath "$x"; done' _ {} +

(您可以对xargs执行相同操作,但只需删除xargs并坚持使用更简单,更快速,更强大的-exec。)

答案 3 :(得分:0)

尝试逐行转换每个文件名"而"循环:

find ... | while read f; do echo "$f" '=>' "$(realpath $f)" ; done

答案 4 :(得分:0)

最短的似乎是使用GNU Parallel:

find /usr/lib -maxdepth 1 -type l -iname "*libblas*"|parallel echo {} '=\> $(readlink -f {})'