【问题标题】:Terminal command to create a .tar.gz files from 1,000,000 .json files (without including any directory)从 1,000,000 个 .json 文件(不包括任何目录)创建 .tar.gz 文件的终端命令
【发布时间】:2016-07-13 19:18:24
【问题描述】:

我有一个包含 1,000,000 个 .json 文件的目录,并使用以下命令仅从 json 文件构建 j.tar.gz(不包括 /Library/WebServer/a/a/e/j/ 路径):

cd /Library/WebServer/a/a/e/j && tar -zcvf j.tar.gz *.json

发生此错误:...Argument list too long。你会建议一个更好的命令来完成这项任务吗?谢谢。

【问题讨论】:

  • 这个目录下还有JSON文件以外的东西吗? (如果没有,为什么要指定*.json?)

标签: bash macos gzip tar


【解决方案1】:

最初的警告:tar 不是标准定义的工具(POSIX 存档器是pax),因此它的行为可能会因平台而异,而没有任何最低保证基线。您的里程可能会有所不同。


由于这被标记为bash,您可以使用<()——一个进程替换——来生成一个文件名,当读取该文件名时,将发出一个子进程的输出,而不需要临时文件。 (如果您的操作系统支持,这通常将实现为 /dev/fd 名称,否则将实现为命名管道)。

如果您只想将cd 应用于tar 命令,您可以按如下方式执行此操作,将其放入子shell 中并使用exec 让子shell 将其自身替换为tar 命令,避免 subshel​​l 否则会产生分叉惩罚:

dir=/Library/WebServer/a/a/e/j
(cd "$dir" && exec tar --null -zcvf j.tar.gz -T <(printf '%s\0' *.json) )

或者,如果您的tar 支持它,您可以使用--include 告诉tar 本身来过滤名称:

tar -C "$dir" --include='*.json' -cvzf "$dir/j.tar.gz" .

注意事项:

  • printf '%s\n' *.json 不受此影响,因为 printf 是内置的 shell;因此,全局结果不会放入 execv-family 系统调用的参数中,因此 ARG_MAX 不适用。
  • find 上使用--null 和在printf 上使用'%s\0'(或-print0,如果您使用find 生成名称列表)可以防止恶意生成的带有文字换行符的名称将任意名称注入您的流中。想想如果有人运行 mkdir -p $'hello/\n/etc/passwd\n.json' 会发生什么——你不希望 /etc/passwd 进入你的压缩包。

【讨论】:

  • 非常感谢您的回答,干杯。
  • j.tar.gz 文件中有一个j 目录。如何将j.tar.gz 中的j 目录权限更改为755。再次感谢。
【解决方案2】:

试试:

find . -type f -name "*.json" > ./include_file && tar -zcvf j.tar.gz --files-from ./include_file

注意:这已在 CentOS/RedHat 6.7 上成功测试。

【讨论】:

  • .json,不是.sh
  • @CharlesDuffy - 我正在编辑它,几乎在你发现它的同时。 :-)(没有足够的 .json 文件来测试它。)但是感谢您的输入。
【解决方案3】:

您的系统设置了一个限制。你可以检查

$ getconf ARG_MAX

我的回报

131072

或者,您可以为tar 创建一个文件列表,并使用-T--files-from F 选项来获取名称,而不是达到最大参数限制的通配符。

【讨论】:

  • 值得一提的是限制的性质(即,它是字节,而不是参数的数量,环境变量而不是命令行长度)。
【解决方案4】:

怎么样:

> cd /Library/WebServer/a/a/e/j
> find . -name '*.json' -maxdepth 1 | xargs tar -czvf j.tar.gz --add-file

它不需要临时文件,也不需要在shell中执行*.json会失败。

在 Ubuntu 上检查过,手头没有 Mac。

【讨论】:

  • 如果您的文件多于ARG_MAX 的容量,这将多次运行tar 并在每次后续调用时覆盖旧的j.tar.gz可以告诉 tar 附加到现有存档,但这不是-c
猜你喜欢
  • 1970-01-01
  • 2011-05-16
  • 2010-11-02
  • 1970-01-01
  • 2018-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多