如何在分叉数量最少的单个目录中创建符号链接?
How to create symlinks in a single directory with the lowest number of forks?
在以下情况下如何在单个目录中创建符号链接:
- 常用方法失败:
ln -s /readonlyShare/mydataset/*.mrc .
-bash: /bin/ln: Argument list too long
find
命令不允许使用以下语法:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' -exec ln -s {} . +
- 使用野外分叉需要几个小时才能完成:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' -exec ln -s {} . ';'
当我需要它的时候我很着急所以我没有探索所有的可能性但是我worked-out同时我做了一些事情
感谢@WeihangJian 的回答,我现在知道 find ... | xargs -I {} ...
和 find ... -exec ... {} ';'
一样糟糕。
我的问题的正确答案是:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' \
-exec sh -c 'ln -s "[=10=]" $@" .' {} +
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -exec ln -s '{}' '+' .
或者如果你喜欢 xargs
:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -print0 |
xargs -0 -P0 sh -c 'ln -s "$@" .' sh
如果您使用的是 BSD xargs
而不是 GNU xargs
,它可以更简单:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -print0 |
xargs -0 -J@ -P0 ln -s @ .
为什么 '{}' '+'
?
引自man find
:
-exec utility [argument ...] {} +
Same as -exec, except that “{}” is replaced with as many pathnames as possible for each invocation of utility. This behaviour is similar
to that of xargs(1). The primary always returns true; if at least one invocation of utility returns a non-zero exit status, find will
return a non-zero exit status.
find
擅长拆分大量参数:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -exec ruby -e 'pp ARGV.size' '{}' '+'
15925
15924
15925
15927
1835
为什么不xargs -I
?
效率低且速度慢,因为 -I
每个参数都执行实用程序,例如:
printf 'foo[=16=]bar' | xargs -0 -I@ ruby -e 'pp ARGV' @
["foo"]
["bar"]
printf 'foo[=18=]bar' | xargs -0 ruby -e 'pp ARGV'
["foo", "bar"]
xargs
也擅长拆分大量参数
seq 65536 | tr '\n' '[=20=]' | xargs -0 ruby -e 'pp ARGV.size'
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
536
为什么 sh -c
?
只有 BSD xargs
有 -J
标志将参数放在命令中间。对于 GNU xargs
,我们需要 sh -c
和 "$@"
的组合来做同样的事情。
find -exec
对比 find | xargs
视情况而定,但我建议您在想要使用所有 CPU 时使用 xargs
。 xargs
可以通过 -P
并行执行实用程序,而 find
不能。
在以下情况下如何在单个目录中创建符号链接:
- 常用方法失败:
ln -s /readonlyShare/mydataset/*.mrc .
-bash: /bin/ln: Argument list too long
find
命令不允许使用以下语法:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' -exec ln -s {} . +
- 使用野外分叉需要几个小时才能完成:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' -exec ln -s {} . ';'
当我需要它的时候我很着急所以我没有探索所有的可能性但是我worked-out同时我做了一些事情
感谢@WeihangJian 的回答,我现在知道 find ... | xargs -I {} ...
和 find ... -exec ... {} ';'
一样糟糕。
我的问题的正确答案是:
find /readonlyShare/mydataset -maxdepth 1 -name '*.mrc' \
-exec sh -c 'ln -s "[=10=]" $@" .' {} +
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -exec ln -s '{}' '+' .
或者如果你喜欢 xargs
:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -print0 |
xargs -0 -P0 sh -c 'ln -s "$@" .' sh
如果您使用的是 BSD xargs
而不是 GNU xargs
,它可以更简单:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -print0 |
xargs -0 -J@ -P0 ln -s @ .
为什么 '{}' '+'
?
引自man find
:
-exec utility [argument ...] {} +
Same as -exec, except that “{}” is replaced with as many pathnames as possible for each invocation of utility. This behaviour is similar
to that of xargs(1). The primary always returns true; if at least one invocation of utility returns a non-zero exit status, find will
return a non-zero exit status.
find
擅长拆分大量参数:
find readonlyShare/mydataset -name '*.mrc' -maxdepth 1 -exec ruby -e 'pp ARGV.size' '{}' '+'
15925
15924
15925
15927
1835
为什么不xargs -I
?
效率低且速度慢,因为 -I
每个参数都执行实用程序,例如:
printf 'foo[=16=]bar' | xargs -0 -I@ ruby -e 'pp ARGV' @
["foo"]
["bar"]
printf 'foo[=18=]bar' | xargs -0 ruby -e 'pp ARGV'
["foo", "bar"]
xargs
也擅长拆分大量参数
seq 65536 | tr '\n' '[=20=]' | xargs -0 ruby -e 'pp ARGV.size'
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
5000
536
为什么 sh -c
?
只有 BSD xargs
有 -J
标志将参数放在命令中间。对于 GNU xargs
,我们需要 sh -c
和 "$@"
的组合来做同样的事情。
find -exec
对比 find | xargs
视情况而定,但我建议您在想要使用所有 CPU 时使用 xargs
。 xargs
可以通过 -P
并行执行实用程序,而 find
不能。