我有一个带有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
。你会建议一个更好的命令来完成这项任务吗?感谢。
答案 0 :(得分:5)
最初的警告:tar
不是标准定义的工具(POSIX归档程序是pax
),因此它的行为可能因平台而异,没有任何最小保证基线。您的里程可能会有所不同。
由于这是为bash
标记的,您可以使用<()
- 进程替换 - 生成一个文件名,在读取时,它将发出子进程的输出而不需要用于临时文件。 (如果您的操作系统支持它们,这通常会被实现为/dev/fd
名称,否则会被实现为命名管道。)
如果您只希望cd
应用于tar
命令,则可以按如下方式执行此操作,将其放在子shell中并使用exec
将子shell替换为自身tar
命令,避免子shell以其他方式创建的fork惩罚:
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;因此,glob结果不会被放入execv
- 家庭系统调用的参数中,因此ARG_MAX
不适用。--null
上的find
和'%s\0'
上的printf
(如果您使用-print0
生成名单列表,则find
)一个恶意生成的名称,带有文字换行符,可以将任意名称注入流中。想想如果有人运行mkdir -p $'hello/\n/etc/passwd\n.json'
会发生什么 - 你不希望/etc/passwd
进入你的tarball。答案 1 :(得分:2)
尝试:
find . -type f -name "*.json" > ./include_file && tar -zcvf j.tar.gz --files-from ./include_file
注意:这已在CentOS / RedHat 6.7上成功测试。
答案 2 :(得分:1)
您的系统设置了限制。你可以检查
$ getconf ARG_MAX
我的回归
131072
或者,您可以为tar
创建一个文件列表,并使用-T
,--files-from F
选项获取名称,而不是使用符合max args限制的globbing。
答案 3 :(得分:0)
如下:
> cd /Library/WebServer/a/a/e/j
> find . -name '*.json' -maxdepth 1 | xargs tar -czvf j.tar.gz --add-file
它不需要临时文件,也不需要在shell中执行*.json
失败。
检查Ubuntu手头没有Mac。