我如何才能以递归方式压缩文件到它们自己的文件夹中?

我如何才能以递归方式压缩文件到它们自己的文件夹中?

我有以下目录结构:

/Data
 - file 1
 - file 2

  /Folder1

   - file 3
   - file 4

  /Folder2
   - file 5
   - file 6

    /Folder3
      - file 7
      - file 8

在 Linux 中,我想要压缩每个目录中的文件(不包括文件夹),并在每个文件夹中创建一个 7z(或 zip)存档,结果如下:

/Data
     Data.7z (Note: this should contain only file1 & 2, not any sub directories)

      /Folder1

       Folder1.7z (this should contain only file3 & 4, not any sub directories)

      /Folder2
       Folder2.7z (this should contain only file5 & 6, no Folder3)

        /Folder3
          Folder3.7z (should contain only file7 & 8)

以下脚本在第一个目录中有效,但在子目录中无效:

for i in */ ; do base=$(basename “$i”) ; cd $base ; 7za a -t7z -r $base * ; .. ; cd .. ; done;

我怎样才能实现这个目标?

答案1

如果你想使用7z,棘手的部分似乎是说服它不是递归;文档中指出的-r-开关似乎不起作用,建议的软件作者提供的解决方法是使用通配符表达式排除子目录-x!*/

因此,鉴于

$ tree Data
Data
├── file1
├── file2
├── Folder1
│   ├── file3
│   └── file4
├── Folder2
│   ├── file5
│   └── file6
└── Folder3
    ├── file7
    └── file8

3 directories, 8 files

然后

find Data -type d -execdir sh -c 'cd "$1" && 7z a "$1".7z -x!*/ && cd -' sh {} \;

结果是

$ tree Data
Data
├── Data.7z
├── file1
├── file2
├── Folder1
│   ├── file3
│   ├── file4
│   └── Folder1.7z
├── Folder2
│   ├── file5
│   ├── file6
│   └── Folder2.7z
└── Folder3
    ├── file7
    ├── file8
    └── Folder3.7z

3 directories, 12 files

例如,我们可以Folder2.7z使用以下方法检查是否仅包含其自己的文件夹的文件

$ 7z l Data/Folder2/Folder2.7z 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_CA.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM)2 Duo CPU     P9600  @ 2.53GHz (1067A),ASM)

Scanning the drive for archives:
1 file, 128 bytes (1 KiB)

Listing archive: Data/Folder2/Folder2.7z

--
Path = Data/Folder2/Folder2.7z
Type = 7z
Physical Size = 128
Headers Size = 128
Solid = -
Blocks = 0

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37 ....A            0            0  file5
2018-02-12 18:37:37 ....A            0            0  file6
------------------- ----- ------------ ------------  ------------------------
2018-02-12 18:37:37                  0            0  2 files

注意:在存在历史扩展运算符的!*/环境中(例如交互式 bash shell),可能需要进行额外的转义。!

答案2

这是未经测试的代码,仅与“echo”一起使用,因为我不喜欢以多个 zip 文件结尾。这是幻想 zip 语法,因为我不知道 7za,但我会解释一下:

find . -type d -execdir /.../ad-hoc.sh {} ";"

脚本 ad-hoc.sh 必须使用绝对路径来寻址,并且不应位于当前路径中,以免影响结果,但它可能位于父目录中:

find . -type d -execdir $PWD/../ad-hoc.sh {} ";"

如果没有设为可执行,则明确调用:

find . -type d -execdir bash $PWD/../ad-hoc.sh {} ";"

Find 将在当前目录中查找,仅查找类型 d(目录)的文件,其中使用参数 {} 执行 bashscript,即找到的目录。

好的 - 我们在目录和子目录中执行的 ad-hoc.sh 是什么?这是另一个发现:

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo zip -o "$dir.zip" {} +

-maxdepth 1 防止 find 搜索子目录,-type 表示仅对文件进行操作。-exec 启动一个命令,用于测试“echo zip ...”,但如果它看起来很有希望(你经常做备份,不是吗?),你 - 好吧,这里开始我的伪代码:-o:= -output“$PWD.zip”,{} + 是文件列表。

tree
.
├── buch-klein.kry
├── buch.kry
├── crypt
│   ├── moveto.sh.crypt
│   └── sub1
│       ├── foo.crypt
│       └── sub2
│           └── bar.crypt
├── original
│   ├── 1
│   │   └── 2
│   │       └── 3
│   ├── moveto.sh
│   └── sub1
│       └── sub2
│           └── up3 -> ../../../nr
├── outputfile.txt
├── rot.sh
└── zoom.sh

find . -type d -execdir $PWD/../ad-hoc.sh {} ";" 
zip -o ./..zip ././buch-klein.kry ././rot.sh ././buch.kry ././zoom.sh ././outputfile.txt
zip -o ./original.zip ./original/moveto.sh
zip -o ./crypt.zip ./crypt/moveto.sh.crypt
zip -o ./sub1.zip ./sub1/foo.crypt
zip -o ./sub2.zip ./sub2/bar.crypt

每个带有扩展名的文件都是常规文件,每个不带有扩展名的文件都是目录或指向目录的符号链接(up3)。

{} 必须是 find -exec 命令的最后一个元素,位于终止符“;”或 + 之前,因此您必须相应地构建 7z 命令。

所以如果你的 7za 命令是

      7za a -t7z -r $dir.7za *

ad-hoc.sh 可能看起来像这样:

#!/bin/bash
dir=$1
find $dir -maxdepth 1 -type f -exec echo 7za -t7z -r "$dir.7za" {} +

相关内容