我有一个包含 2Gb 图像的文件夹,其中有几层深的子文件夹。
我想仅将N
每个(子)文件夹的文件存档在 tar 文件中。我尝试使用find
当时tail
但tar
无法让它工作。这是我尝试过的(假设N = 10
):
find . | tail -n 10 | tar -czvf backup.tar.gz
...输出此错误:
Cannot stat: File name too long
这是怎么回事?想一想 - 即使它有效,我认为它只会压缩所有文件夹的前 10 个文件,而不是 10 个文件每个文件夹。
如何获取N
每个文件夹的文件? (无需文件订单)
答案1
如果您pax
支持该-0
选项,请使用zsh
:
print -rN dir/**/*(D/e:'reply=($REPLY/*(ND^/[1,10]))':) |
pax -w0 | xz > file.tar.xz
它包括列表中按文件名排序的每个目录的前 10 个非目录文件。您可以通过添加 glob 限定符来选择不同的排序顺序om
(按修改时间排序,Om
以反转顺序)、oL
(按长度排序)、non
(按名称排序但按数字排序)...
如果您没有标准pax
命令,或者不支持-0
但您有 GNUtar
命令,您可以执行以下操作:
print -rN -- dir/**/*(D/e:'reply=($REPLY/*(ND^/[1,10]))':) |
tar --null -T - -cjf file.tar.xz
如果您无法使用zsh
,但可以访问bash
(GNU 项目的 shell),您可以这样做:
find dir -type d -exec bash -O nullglob -O dotglob -c '
for dir do
set -- "$dir/*"; n=0
for file do
if [ ! -d "$file" ] || [ -L "$file" ]; then
printf "%s\0" "$file"
(( n++ < 10 )) || break
fi
done
done' bash {} + | pax -0w | xz > file.tar.xz
但这会大大降低效率。
答案2
假设您的主目录/tmp/dir
中您只想将其下每个(子)文件夹的 N 个(例如 N=10)个文件归档到一个backup.tar.gz
文件中。
示例:tree
/tmp/dir
dir/
├── one
│ ├── one10.txt
│ ├── one11.txt
│ ├── one1.txt
│ ├── one2.txt
│ ├── one3.txt
│ ├── one4.txt
│ ├── one5.txt
│ ├── one6.txt
│ ├── one7.txt
│ ├── one8.txt
│ ├── one9.txt
│ └── one_deep
│ ├── one_deep1
│ ├── one_deep10
│ ├── one_deep11
│ ├── one_deep2
│ ├── one_deep3
│ ├── one_deep4
│ ├── one_deep5
│ ├── one_deep6
│ ├── one_deep7
│ ├── one_deep8
│ └── one_deep9
├── three
│ ├── three10.txt
│ ├── three11.txt
│ ├── three1.txt
│ ├── three2.txt
│ ├── three3.txt
│ ├── three4.txt
│ ├── three5.txt
│ ├── three6.txt
│ ├── three7.txt
│ ├── three8.txt
│ ├── three9.txt
│ └── three_deep
│ ├── three_deep1
│ ├── three_deep10
│ ├── three_deep11
│ ├── three_deep2
│ ├── three_deep3
│ ├── three_deep4
│ ├── three_deep5
│ ├── three_deep6
│ ├── three_deep7
│ ├── three_deep8
│ └── three_deep9
代码:
cd /tmp; for i in `find dir/* -type d`; do find $i -maxdepth 1 -type f | tail -n 10 | xargs -I file tar -rf backup.tar file; done; gzip backup.tar
这将创建一个backup.tar.gz
包含 10 个文件的子文件夹/tmp/dir
。
答案3
由于 的输出find
是扁平的,因此如果不查看路径,您实际上无法知道哪些文件属于同一目录。另一种方法是使用多个find
s(每个文件夹一个),而无需查看路径。这就是我所做的。为了压缩每个子文件夹最多 10 个文件,请使用如下内容:
for dir in $(find . -type d); do
find "$dir" -maxdepth 1 -type f -printf "\"%p\"\n" | tail -10
done | xargs tar cvfz backup.tar.gz
这会递归查找当前文件夹中的所有目录。对于每个目录,它最多查找 10 个文件确切地该文件夹 ( -maxdepth 1
)。整个循环完成后,tar
将对循环输出的所有文件执行该命令。我还通过引用$dir
并find
使用该选项打印引号内的每个文件名来计算带有空格的目录和文件夹名称-printf
。
答案4
对目录名使用哈希,并且仅在哈希值计数低于阈值时才发出文件名。例如
find . -depth -type f \
| perl -MFile::Spec -nle '(undef,$d,$f)=File::Spec->splitpath($_); print if $seen{$d}++ < 3' \
| tar ...