Зіпсувати всі файли в каталозі?


483

Чи є спосіб скопіювати всі файли в заданий каталог за допомогою zipкоманди? Я чув про використання *.*, але хочу, щоб він працював і для файлів без розширень.


2
Ви спробували перейти на один рівень вгору від потрібного каталогу та робити zip myarch.zip mydir/*?
Джозеф Р.

13
а ще кращеzip -r myarch.zip mydir/*
Адам

25
або кращеzip -r myarch.zip mydir
ctrl-alt-delor

*.*означає будь-який файл із крапкою. У cp / m та dos усі файли мали крапку, і це змусило вас ввести її (не міг зробити *). Тому люди приходили бачити *.*всі файли. Врешті-решт, Microsoft додав довгі імена файлів, які можуть мати нуль або більше крапок. Щоб знайти файл, який має крапку у вікні, потрібно ввести *.*.*.
ctrl-alt-delor

Відповіді:


705

Ви можете просто використовувати *; в цьому немає потреби *.*. Розширення файлів не є особливими для Unix. *відповідає нулю або більше символів - включаючи крапку. Таким чином, це відповідає foo.png, тому що це нуль або більше символів (точніше сім).

Зауважте, що *за замовчуванням файли не відповідають файлам, що починаються з крапки (ні *.*). Це часто те, що ти хочеш. Якщо ні, в bash, якщо ви shopt -s dotglobцього хочете (але все одно виключаєте .і ..). Інші оболонки мають різні способи (або взагалі відсутні) включення точкових файлів.

Крім того, zipтакож є -r(рекурсивний) варіант робити цілі дерева каталогів одночасно (і не потрібно турбуватися про проблему з dotfile):

zip -r myfiles.zip mydir

де mydirкаталог, що містить ваші файли. Зауважте, що створений zip буде містити структуру каталогів, а також файли. Як вказує Петерф у своєму коментарі, це зазвичай сприймається як гарна річ: вилучення zip акуратно зберігатиме всі витягнуті файли в одному підкаталозі.

Ви також можете сказати zip, щоб не зберігати шляхи з параметром -j/ --junk-paths.

zipКоманда поставляється з документацією розповісти вам про всі свої (багато) варіантів; введіть, man zipщоб побачити цю документацію. Це не унікально для блискавки; ви можете отримати документацію для більшості команд таким чином.


9
Ви можете додати, що вважається хорошою практикою містити все в архіві в каталозі вищого рівня - щоб не забруднити поточний каталог на видобуток.
петерф

@peterph зроблено. Хоча я боюся, що це менш умова в zip-файлах, ніж, наприклад, у tarfiles.
дероберт

на жаль, так. Можливо, завдяки спадщині windows drag'n'drop до робочого столу та Linux-спадщині роботи з вихідними кодами.
петерф

2
Майте на увазі, що *обшивка оболонки не включає точкові файли (тобто імена файлів, що починаються з .). Це ще одна перевага, пов’язана зі всім каталогом по імені.
мрб

Але використання -r включає сам каталог, який порушує те, що я роблю. Не включатиме * .і ..?
tkbx

11

У моєму випадку я хотів зафіксувати кожен файл у власному архіві, тому зробив наступне (в zsh):

$ for file in *; do zip ${file%.*}.zip $file; done

1
Тут немає mkv? Також нічого тут не є особливо zshспецифічним. Ви хочете правильно цитувати будь-яку змінну, що містить ім'я файлу, тому zip "${file%.*}.zip" "$file"з подвійними лапками навколо обох змінних.
трійка

1
@tripleee По-перше, дякую за вказівку на моє помилкове посилання на mkv. По-друге, цитування аргументів непотрібне zsh, на відміну від bash. Тому я уточнив, що це команда для zsh.
Радон Росборо

Заміна останньої крапки з двокрапкою на амперсанд може значно прискорити її (Якщо кількість файлів у каталозі є розумною ...). В іншому випадку find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'-Pкоригуванням залежно від потоку процесора ...) (Багато залежностей від GNU ...)
Герт ван ден Берг

5

Іншим способом було б використання find і xargs: (це може включати каталог "." В zip, але він все одно повинен правильно витягуватися. З мого тесту zip позбавив крапку перед стисненням) find . -type f -exec zip zipfile.zip {} +

( +Можна замінити, \;якщо ваша версія findне підтримує +кінець для exec. Це буде повільніше, хоча ...)

Це за замовчуванням включає всі підкаталоги. Якщо знайти GNU, це -maxdepthможе запобігти.


(на відміну від застосованих рішень *, це буде включати в себе dotfiles і не перепаде, якщо в каталозі буде занадто багато файлів)
Герт ван ден Берг,

1

Ще один (повільний) спосіб зробити це (який додає один файл до zip одночасно):

for f in * .[^.]*; do
    [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well
    zip zipfile.zip "$f" # If directories are included, you probably want to add -r
done

У цьому є проблеми з dotfile *(обхідний доданий), і він би запустив ZIP один раз для кожного файлу, додаючи його до архіву. У bashньому було б оброблено велику кількість файлів.

Це було б повільніше, ніж більшість інших методів, але відносно простий.


1
Я б сказав, що це менш просто, ніж прийнята відповідь, і повільніше, що спонукає до запитання: "Чому хтось би це робив?". Якщо ви можете відповісти на це питання, я рекомендую вам поставити цей контекст у своїй відповіді, інакше я вважаю, що це погана відповідь на старе питання, на яке вже є хороша відповідь.
Centimane

@Centimane: Я зазначу обмеження. Я вважаю, що це має виховне значення. (Якщо не пропускати каталоги, це досить просто). Якщо ви хочете набагато швидше відповісти, використовуючи натомість (стандартний) зовнішній інструмент, моя інша відповідь це стосується . (із видаленою обробкою точкових файлів (що впливає на правильність без їх відсутності, зазначене у питанні), я вважаю, що це досить елегантно):for f in *; do zip zip.zip "$f"; done
Герт ван ден Берг

1
Зауважте, що прийнята відповідь не використовує зовнішню команду і буде швидшою. У якому сценарії ця відповідь була б корисною?
Centimane

@Centimane З tar, коли є більше файлів, ніж те, що bash може передаватись як параметри. (знайти + xargs краще, бо петлі простіші ...). Це (унікальна) відповідь на питання. Звичайно, це не оптимальна відповідь. (Неоптимальні відповіді все ще можуть бути корисними для подібних проблем, якщо хтось має дещо іншу ситуацію - наприклад, бажаючи, щоб файл tar-файлу містив у ньому каталоги)
Герт ван ден Берг,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.