在 Zsh 中,
- 要复制常规文件,我可以使用
cp source-dir/*(.) dest-dir/
- 复制目录:
cp source-dir/*(/) dest-dir/
- 复制其他所有内容,例如符号链接、管道和设备:
cp source-dir/*(^./) dest-dir/
但是,如何才能复制符号链接(例如,复制到常规文件)而不是符号链接目录呢?或者反过来,复制符号链接(复制到目录)而不是符号链接(复制到常规文件)呢?
在 Zsh 中,
cp source-dir/*(.) dest-dir/
cp source-dir/*(/) dest-dir/
cp source-dir/*(^./) dest-dir/
但是,如何才能复制符号链接(例如,复制到常规文件)而不是符号链接目录呢?或者反过来,复制符号链接(复制到目录)而不是符号链接(复制到常规文件)呢?
使用
-
以下限定符的限定符在符号链接解析之后应用,并结合@
(在-
!)之前测试符号链接。来自
info zsh qualifiers
(最新版本的 zsh也在网上):请记住,如果您启用完成(使用
compinit
),您可以Tab像往常一样按 获得有关限定符的内联帮助,您将看到:可能还值得注意的是,这里的符号链接解析是指完整的符号链接解析。例如,
*(@-.)
还将选择一个文件,该文件是指向另一个文件的符号链接,而该文件本身是指向常规文件的符号链接(如 GNUfind
的-xtype f
或 的[
)-f
。如上所示,*(@-@)
,same as-@
不适用于符号链接到符号链接,而适用于损坏的符号链接(与 GNUfind
的相同-xtype l
),即在完整的符号链接解析后无法确定为除符号链接以外的任何文件²。要仅检查符号链接的直接目标的类型,它会更加复杂,因为您需要手动完成一级符号链接解析³。
可能是这样的:
您可以使用来
*(@e[target_of_type X])
选择直接目标类型为的符号链接X
,其中X
这里基于的s
tring 表示的第一个字符mode
(与 输出的第一个字段相同ls -l
),因此-
对于常规、d
目录、l
符号链接等:¹ 严格来说,这应该是“任何符号链接,其 'stat' 系统调用失败”,尽管对于普通读者来说可能不太清楚。这是在同一文件上
-
从使用切换lstat()
到使用,但如果失败,则限定符将根据结果应用。这就是为什么选择损坏的符号链接,但也会引起混淆,例如,旨在在符号链接解析后返回非空文件,也会返回目标长度大于 0 的损坏符号链接,因此任何损坏的符号链接,因为符号链接目标不能是空字符串。无论如何,在这种情况下可能更合适,无论该问题如何。stat()
stat()
lstat()
-@
*(-L+0)
*(-.L+0)
² 例如,因为链接链包含一个不存在的文件或遍历您没有搜索权限的目录,或者存在符号链接循环...
³ 与让系统进行解析相反。在基于 Linux 的系统上,对于中的魔术
/proc/*/fd
符号链接,手动执行该解析可能会产生错误的结果,因为这些符号链接的公布目标路径(由系统调用返回readlink()
)不一定指向相应的 上打开的文件fd
。当文件已被删除时尤其如此,其中readlink()
返回附加到它的原始路径(deleted)
,而stat()
上的 会设法返回已删除文件的信息。由于这不是符号链接的属性,而是符号链接的目标的属性,因此没有 glob 可以执行此操作。
因此,您必须编写一个
for
遍历所有符号链接的循环(for symlink in source-dir/*(@); do…
),并且在其中,必须使用readlink "${symlink}"
来获取单个符号链接的目标,然后检查[[ … ]]
指向目录的符号链接([[ -d…
),否则(||
)continue
指向下一个符号链接。