从 zip 中排除顶层文件但包含目录和内容

从 zip 中排除顶层文件但包含目录和内容

这让我很抓狂。谷歌搜索结果都是相反的情况。

所以我有一个像这样的目录结构:

MyFiles
|    file1
|    file2
|    file3
|    MoreFiles
|    |    file4
|    |    file5

我想要的是一个存档(最好是 zip,因为我正在将这个过程传递给非 tar 用户,但如果答案显示了如何在 zip 和 tar 中操作,则会获得加分),如下所示:

archive.zip
|    MoreFiles
|    |    file4
|    |    file5

这样顶级文件就被排除了,但子目录其文件包括。

到目前为止,我能想到的最好的办法是:

zip -r 存档.zip MyFiles -x "

但这会排除每一层的所有文件,所以我最终只得到目录结构。我只想排除直接位于目标目录中的目录。

哦!实际上,我的实际用例是排除一个特定子目录的内容,因此从下一个最深层开始工作并不是一个解决方法。真实情况是:

MyFiles
|    file1
|    file2
|    file3
|    Level1Files1
|    |    file4
|    |    file5
|    |    Level2Files1
|    |    |    file6
|    |    |    file7
|    |    Level2Files2
|    |    |    file8
|    |    |    file9
|    Level1Files2
|    Level1Files3

最终目标是包含顶层的所有内容,但排除特定子目录内的文件,但不排除第一个子目录内的子目录或它们的内容,因此,如果我想排除上面的子目录 Level1Files1 的顶层文件,结果将是:

archive.zip
|    file1
|    file2
|    file3
|    Level1Files1
|    |    Level2Files1
|    |    |    file6
|    |    |    file7
|    |    Level2Files2
|    |    |    file8
|    |    |    file9
|    Level1Files2
|    Level1Files3

答案1

创造性地使用通配符。

$ tree MyFiles
MyFiles
├── dira
│   ├── file1
│   ├── file2
│   └── file3
├── dirb
│   ├── file1
│   ├── file2
│   └── file3
├── dirc
│   ├── file1
│   ├── file2
│   └── file3
├── file1
├── file2
└── file3

我们需要做的只是不告诉 zip 有关根文件的信息。Bash 通配符允许我们指定这一点,请zip -r archive.zip MyFiles/*/注意,通配符的格式使其只能匹配目录。使用它,我们得到:

$ zip -r archive.zip MyFiles/*/
  adding: MyFiles/dira/ (stored 0%)
  adding: MyFiles/dira/file1 (stored 0%)
  adding: MyFiles/dira/file2 (stored 0%)
  adding: MyFiles/dira/file3 (stored 0%)
  adding: MyFiles/dirb/ (stored 0%)
  adding: MyFiles/dirb/file1 (stored 0%)
  adding: MyFiles/dirb/file2 (stored 0%)
  adding: MyFiles/dirb/file3 (stored 0%)
  adding: MyFiles/dirc/ (stored 0%)
  adding: MyFiles/dirc/file1 (stored 0%)
  adding: MyFiles/dirc/file2 (stored 0%)
  adding: MyFiles/dirc/file3 (stored 0%)

$ less archive.zip
Archive:  archive.zip
Zip file size: 1960 bytes, number of entries: 12
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dira/file3
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirb/file3
drwxrwxr-x  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file1
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file2
-rw-rw-r--  3.0 unx        0 bx stor 15-Apr-08 00:30 MyFiles/dirc/file3
12 files, 0 bytes uncompressed, 0 bytes compressed:  0.0%

仅子目录及其内容。

对于奖励问题:

tar -xcvf archive.tar.gz MyFiles/*/

更具体的排除需要非常有创意地使用通配符、正则表达式、find和管道。我想到了一些想法,但都不太好或可靠。此时,您开始编写脚本,并且您不妨只使用循环进行迭代。

编辑:有一种不太疯狂的方法可以使用子目录来实现。我认为。

zip -r archive.zip MyFiles/*/ -x \
         $(find ./MyFiles/subdir/toexclude/topfiles -maxdepth 1 -not -type d)

注意转义的换行符 - 这应该都是一行。根据需要进行修改。我已经测试过了,它排除了其中的文件,MyFiles/subdir/toexclude/topfiles但包括了它的 3 个子目录等等。

对于你的例子来说这应该可以做到:

$ cd MyFiles
$ zip -r archive.zip * -x $(find -maxdepth 1 ./Level1Files1 -not -type d)

相关内容