我有一个文件夹,里面有大约 20K 个文件。这些文件按照模式命名xy_{\d1,5}_{\d4}\.abc
,例如xy_12345_1234.abc
。我想使用以下命令压缩其中的前 10K 个文件:
ls | sort -n -k1.4,1.9 | head -n10000 | xargs tar -czf xy_0_10000.tar.gz
但生成的文件里面只有大约 2K 个文件。
ls | sort -n -k1.4,1.9 | head -n10000 | wc -l
但正如预期的那样,返回了 10000。
在我看来,我误解了这里的一些基本内容......
我在 Linux Mint 17.1 上使用 zsh 5.0.2,GNU tar 1.27.1
编辑:
@Archemar 建议的分叉听起来很合理,最新的分叉会覆盖生成的文件 - 该文件包含文件的“尾部” -7773到9999。
的结果xargs --show-limit
:
Your environment variables take up 3973 bytes POSIX upper limit on argument length (this system): 2091131 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2087158 Size of command buffer we are actually using: 131072
在我的情况下,替换-c
为-r
或-u
不起作用。错误消息是tar: Cannot update compressed archives
同时使用-r
和-u
是无效的,并且会失败tar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option
替换似乎也无效,并且失败了,-c
尽管我没有意识到这个问题并且对我来说似乎是不连贯的。-a
tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options
azf
Acdtrux
编辑2:
-T看起来是个好方法,我也找到了一个例子这里。
但是当我尝试
ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T -
我明白
tar: option requires an argument -- 'T'
好吧,也许文件名没有到达 tar?但看起来它们确实到达了,因为当我执行
ls | sort -n -k1.4,1.9 | head -n10000 | tar --null -czf xy_0_10000.tar.gz -T -
我明白
tar: xy_0_.ab\nxy_1_...<the rest of filenames separated by literal \n>...998.ab Cannot stat: File name too long
那么为什么 tar 看不到文件名?
答案1
您已达到 xargs 限制吗?
xargs --show-limit
尝试 :
- 创建一个虚拟
.tgz
文件tar czf xy_0_10000.tar.gz /hello/world
- 替换
-czf
为-Azf
当 xarg 达到其限制时,它将派生命令,因此您最终运行的命令是
tar czf xy_0_10000.tar.gz file1 file2 .... file666
tar czf xy_0_10000.tar.gz file667 file668 ... file1203
tar czf xy_0_10000.tar.gz file1024 ... file2000
由于每个 tar 都会覆盖前一个 tar,因此您应该只会获得最后一次tar c
运行。
编辑:
1)根据附加,方法是(要么) man tar
unbuntu,-a
-r 似乎等效于-A, --catenate, --concatenate
2)zip
(不是gzip
)可用于添加文件,也许 gzip 选项可以解决问题。(使用 | xargs zip -qr xy_0_0000.zip
,这将生成一个 zip 文件,而不是 .tar.gz)
3)使用@rsanchez的解决方案
以适当的方式向tar添加选项很重要,尝试
ls | sort -n -k1.4,1.9 | head -n10000 |tar -czf xy_0_10000.tar.gz -T -
其中 --T -
表示使用选项-T
并用作-
参数-T
(您可以生成文件列表/tmp/foo.lst
,然后使用-T /tmp/foo.lst
)
答案2
答案3
我想补充一下其他两个答案嘚解决方案,既不解析 ls,也不需要参数。但是,我现在不确定它是否也受到命令行长度的限制。
定义一个函数,通过修改来生成所需的排序键
$REPLY
。sortkey() { REPLY=${REPLY[4,9]} }
这相当于你的
sort -n -k1.4,1.9
$files
使用上述函数生成按文件名排序的数组:files=(*(o+sortkey))
这相当于
ls | sort -n -k1.4,1.9
返回前 10 000 个文件
${files[0,9999]}
这相当于
ls | sort -n -k1.4,1.9 | head -n10000
所以,总的来说,这应该可以解决问题:
sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}