![从 zip 中排除顶层文件但包含目录和内容](https://linux22.com/image/1446362/%E4%BB%8E%20zip%20%E4%B8%AD%E6%8E%92%E9%99%A4%E9%A1%B6%E5%B1%82%E6%96%87%E4%BB%B6%E4%BD%86%E5%8C%85%E5%90%AB%E7%9B%AE%E5%BD%95%E5%92%8C%E5%86%85%E5%AE%B9.png)
这让我很抓狂。谷歌搜索结果都是相反的情况。
所以我有一个像这样的目录结构:
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)