我正在尝试编写一个简单的命令,为特定目录中的所有文件创建符号链接(是的,完全一样,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
, likecp
或mv
创建指向具有相同基本名称的另一个参数的链接里面那个目录。
或者与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:P
for realpath
)。
在这里,您只需要:
find "$(realpath -- "$FROM_DIR")" -mindepth 1 -maxdepth 1 \
-exec ln -sft "$TO_DIR" -- {} +
不过(-t
也是 GNU 扩展)。那个不受争论太多如果 中的文件太多,您可能会遇到错误$TO_DIR
(在 中,您可以通过使用或加载模块来获取 的内置版本来zsh
解决此问题)。zargs
zsh/files
ln
另请参阅这些问答,了解您的尝试中的其他问题: