1

Это сводит меня с ума. Все результаты Google для обратного сценария.

Итак, у меня есть структура каталогов, как:

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

И что мне нужно, так это архив (желательно zip, когда я передаю процесс пользователям, не являющимся tar, но бонусные баллы за ответы, показывающие, как это сделать в zip и tar), который выглядит следующим образом:

archive.zip
|    MoreFiles
|    |    file4
|    |    file5

Таким образом, файлы верхнего уровня исключаются, но подкаталоги и их файлы включены.

Пока лучшее, что я мог придумать, это:

zip -r archive.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 ответ1

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 и каналов. На ум приходит пара идей, но ничего красивого или надежного. В этот момент вы попадаете в сценарии, и вы можете просто повторить цикл.

Изменить: есть не совсем безумный способ сделать это с subdirs. Я думаю.

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)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .