答案1
通过zsh
,您可以使用@
glob 限定符将 glob 扩展限制为以下类型的文件符号链接:
tar -czf file.tar.gz -- *(@)
要还包含隐藏的文件,请添加D
(对于D
ot 文件)限定符:
tar -czf file.tar.gz -- *(D@)
在其他 shell 中,您可以用来find
查找类型的文件符号链接并将它们传递给tar
:
find . ! -name . -prune -type l -exec tar -zcf file.tar.gz {} +
但请注意与 zsh 方法相比的一些差异:
包含隐藏文件,需要一些:
LC_ALL=C find . ! -name . -prune ! -name '.*' -type l -exec tar -zcf file.tar.gz {} +
可靠地排除它们。
文件列表未排序。
前缀
./
被添加到存档成员中(这就是我们不需要 的原因--
)。如果有很多匹配的文件,
find
可能最终会调用tar
多次,这意味着file.tar.gz
只会包含上次运行的文件。 (在这些情况下,使用 zsh 方法,您最终可能会得到参数列表太长错误代替)。
通过moreutils 中的find
、sort
、tar
和 的GNU 实现,您可以通过执行以下操作来解决这些问题:ifne
LC_ALL=C find . ! -name . -prune ! -name '.*' -type l -printf '%P\0' |
sort -z |
ifne tar -zcf file.tar.gz --null -T -
在哪里:
- 我们用来
-printf '%P\0'
打印文件相对于起始目录 (.
) 的路径,因此例如它打印link
而不是./link
.它以 NUL 分隔,因为 0 是唯一不能出现在文件路径中的字节值。 sort -z
根据语言环境的排序规则对这些 NUL 分隔的记录进行词法排序,就像 zsh glob 一样。- 我们将该列表
tar
通过其标准输入上的管道传递,而不是作为参数传递,以避免系统对参数大小的限制。 ifne
需要覆盖没有文件的情况,在这种情况下,如果发现没有它,GNUtar
1.34 至少似乎正在创建一个大多稀疏的 10KiBfile.tar.gz
填充零。
无论如何,请记住,不应在全局可写目录中创建具有固定名称的文件,因为/tmp
这是一种安全风险。
答案2
在命令行上,人们通过组合多个命令来解决复杂的任务。如果我们知道符号链接的名称中没有空格和特殊字符,则可以简单地使用find
with命令替换:
tar -czf /tmp/test.tar.gz `find -maxdepth 1 -type l`
例如,这不适用于名称中的空格或分号。在这种情况下,一个简单的解决方案是将列表写入临时文件:
TMPLIST=`mktemp`
find -maxdepth 1 -type l -print0 > $TMPLIST
tar -czf /tmp/test.tar.gz --null --files-from $TMPLIST
rm $TMPLIST