使用 xargs 输入进行命令替换

使用 xargs 输入进行命令替换

我正在尝试编写一个简单的命令,为特定目录中的所有文件创建符号链接(是的,完全一样,lndir但我无法使用它,所以我尝试模仿它)。

find我使用+尝试了以下操作xargs

find $(realpath ${FROM_DIR}) -maxdepth 1 -print0 | xargs -0 -I{} ln -sfn {} ${TO_DIR}/$(basename {})

但问题是 shell $(basename {})在执行该行之前替换一次,而不是每个参数。

将其写为循环如下所示:

for i in $(find $(realpath ${FROM_DIR}) -maxdepth 1)
do
    ln -sfn $i ${TO_DIR}/$(basename $i)
done

这可行,但速度相对较慢。我想知道这xargs是否也可以使用来完成。

答案1

听起来像你想要的:

ln -sf -- "$(realpath -- "$FROM_DIR")"/* "$TO_DIR/"

当最后一个参数是目录时,ln, likecpmv创建指向具有相同基本名称的另一个参数的链接里面那个目录。

或者与zsh

ln -sf -- $FROM_DIR:P/* $TO_DIR/

如果无法确定 的真实路径$FROM_DIR或在 中找不到文件,这也会表现得更好$FROM_DIR

(添加D限定符还可以为隐藏文件创建符号链接)。

或者,如果由于某种原因您确实需要对ln每个文件调用一次:

for f ($FROM_DIR:P/*(ND)) ln -sfT -- $f $TO_DIR/$f:t

(请注意,-n-T是非标准扩展)。

要使用 shell 命令替换 with xargs(或者这里, with find -exec, usingxargs是毫无意义的),您需要它们来运行 shell:

TO_DIR=$TO_DIR find "$(realpath -- "$FROM_DIR")" -mindepth 1 -maxdepth 1 \
  -exec sh -c '
    for file do
      ln -sfn -- "$file" "$TO_DIR/$(basename -- "$file")"
    done' sh {} +

但请记住,它basename不能用于任意文件的命令替换,因为命令替换会删除所有尾随换行符(此处存在相同的问题$(realpath))。你最好在这里使用sh's${file##*/}zsh $file:t( $FROM_DIR:Pfor realpath)。

在这里,您只需要:

find "$(realpath -- "$FROM_DIR")" -mindepth 1 -maxdepth 1 \
  -exec ln -sft "$TO_DIR" -- {} +

不过(-t也是 GNU 扩展)。那个不受争论太多如果 中的文件太多,您可能会遇到错误$TO_DIR(在 中,您可以通过使用或加载模块来获取 的内置版本来zsh解决此问题)。zargszsh/filesln

另请参阅这些问答,了解您的尝试中的其他问题:

相关内容