使用标准输入中的文件列表调用 tar 的可移植方法

使用标准输入中的文件列表调用 tar 的可移植方法

我想从目录的内容创建 .tgz。我还想./从焦油内容中删除前导“”。
我是这样做的:

cd /path/to/files/ && find . -type f | cut -c 3- | xargs czf /path/to/tgz/myTgz.tgz

最近学到的使用xargs可能不是实现此目的的最佳方法,因为如果 cmdline arg 列表太长,xargs可能会调用多次,并且建议我利用从标准输入读取输入文件列表的能力。我最终发现tartar本文关于如何做到这一点。不过我发现这个推荐...

cd /path/to/files/ && find . -type f | cut -c 3- | tar czf foo.tgz -T -

……好像不方便携带。它在我的开发 PC 上运行良好,但在 busybox 目标上,运行相同的命令时出现以下错误:

tar: can't open '-': No such file or directory

所以我的问题:是否有一种真正可移植/全局的方法来调用通过从标准输入(而不是命令行参数)提供输入文件tar来创建 a ?.tgz

(我无法选择安装/ /tar等替代品。)gnutarbsdtar

(第二个问题:为什么“ -T -”参数tar表示“从中读取文件stdintar手册页中,我只能找到“ -T”的意思:

获取要从 FILE 中提取或创建的名称

...但我看不到任何对普通“ -”的引用)

答案1

这是一种常见的约定,在需要输入文件名的情况下解释-为标准输入,在需要输出文件名的情况下解释为标准输出。因为这是一个常见的约定,所以 GNU tar 手册页中的简短帮助摘要没有提及它,但是完整手册(通常可以通过 本地获得info tar)。这POSIX 命令行实用程序语法指南包括这个约定,所以它相当广泛(但它始终是程序作者的选择)。

BusyBox 实用程序确实遵循此约定。但是手动的没有提到tar支持该选项-T,我发布的机器上的版本也没有提到(Ubuntu 上为 1.27.2)。我不知道为什么您会收到错误“:没有这样的文件或目录”而不是“无效选项 - 'T'”。看来您将其tar解释-T为不带参数的选项,然后将其视为-文件名。由于在这种情况下 tar 需要一个文件名放入档案,而不仅仅是一些内容来自文件的,使用 stdin/stdout 解释是没有意义的-

BusyBox 实用程序在设计上支持一组有限的功能,因为它们适用于嵌入式系统,而 GNU 实用程序的高级功能不适合这些系统。显然,-TBusyBox 设计者认为这不是一个有用的功能。

我不认为 BusyBox tar 有任何方法从标准输入读取文件名。如果需要归档目录中的文件子集,并且不需要归档中的任何符号链接,解决方法是在临时目录中创建符号链接林并归档此临时目录。

目前尚不清楚您使用的确切原因find。如果您只想要当前目录中的文件,为什么不呢tar czf /path/to/archive.tgz -- *?如果存在子目录并且您想要归档这些子目录中的文件,而不是目录本身(大概是为了将它们恢复到目录结构必须存在但可能具有不同权限的位置),那么您的命令确实有意义。在这种情况下,领先./不会造成任何伤害。

答案2

我知道这是一个愚蠢的答案,也许对你不利,但如果你只是......

cd /path/to/files/ && find . -type f | cut -c 3- >/tmp/temp.txt 
tar czf foo.tgz -T /tmp/temp.txt

答案3

您可以将该-u/--update选项与 结合使用xargs。我只是尝试并证明它有效,我tar使用以下方法将文件名参数一一提供xargs -n 1

find top_of_tree/ -type f | xargs -n 1 tar -uf archive.tar

当然,这只是一个概念证明。在您的情况下,允许将参数列表分成不超过参数长度限制的较大部分可能更实际xargs,以避免大量调用tar

find top_of_tree/ -type f | xargs tar -uf archive.tar

前提条件是tar您平台上的所有实现都至少支持其中一个-u/--update标志。

编辑:-u/--update标志允许tar创建以及附加到存档。

我刚刚注意到,不幸的是,您无法更新压缩档案(tgz,使用该-c标志创建)。但是,您无论如何都可以先创建一个非压缩存档,然后压缩结果。

tar另外,我使用带有连字符(“-”字符)的标志不应让您感到困惑。它接受这两种形式。在我的例子中,-uf相当于uf你的例子。

至于该-选项,它可能没有记录在手册页中,tar因为它是处理流和命名文件的命令行工具的非常常见的 Unix 约定。 -通常是过滤器的特殊参数,并将标准输入流命名为文件。

答案4

这篇文章很有帮助,但这里有一个真实的示例,我只想备份特定文件系统中的文件夹结构,并希望 tar 从 stdin 读取所述文件夹结构:

find /kelinda/ -type d | tar cvf /tmp/kelinda.folders.tar --no-recursion -T -

注意:/kelinda 只是我拥有的一个存在于外部硬盘上的文件系统。

因此,您可以使用 find 来查找所需内容的列表,并将其通过管道传输到 tar 中。 “-T -”将从标准输入读取输入文件(如其他帖子中所述),然后我添加“--no-recursion”以防止 tar 备份我不想要的其他文件。

换句话说,使用 find 以及 --no-recursion 选项,为您提供了一种备份文件和/或文件夹的精确列表的方法,然后将其与“-T -”选项结合起来,让您可以读取所述列表来自标准输入的输入。

相关内容