Рекурсивно разархивируйте файлы, а затем удалите исходный файл, оставив разархивированные файлы на месте из оболочки.

Я до сих пор понял, как использовать find для рекурсивного распаковывания всех файлов:

find . -depth -name `*.zip` -exec /usr/bin/unzip -n {} \; 

Но я не могу понять, как удалить zip-файлы по одному после извлечения. Добавление rm *.zip в -a -exec приводит к удалению большинства zip-файлов в каждом каталоге до их извлечения. Прохождение через сценарий, содержащий команду rm (с включенным -i для тестирования), приводит к тому, что find не находит никаких *.zip-файлов (или, по крайней мере, это то, на что он жалуется). Конечно, во многих именах файлов есть пробелы, но на данный момент синтаксис в команде sed для добавления _ немного выше моего понимания. Спасибо за помощь!


person Ben    schedule 08.04.2011    source источник
comment
Что значит recursively, молния в молнию? Для сложных задач лично я написал бы вспомогательный скрипт (скажем, unzip-and-rm.sh) и -exec этот скрипт.   -  person Xiè Jìléi    schedule 08.04.2011
comment
Прошу прощения, если я был недостаточно ясен. Дерево каталогов идет как минимум на шесть или семь уровней вниз, причем zip-файлы находятся на самых глубоких уровнях. Каждый zip-файл содержит два других файла, и я хочу оставить остальные файлы нетронутыми, а затем удалить zip-файл. Моя первоначальная попытка заключалась в том, чтобы просто подключить unzip-and-rm к сценарию и -exec его, но он не смог найти какие-либо zip-файлы, и я подозреваю, что это связано с пробелами в именах файлов.   -  person Ben    schedule 08.04.2011
comment
Я не знаю, почему it fails to find any zip files, я не могу в это поверить, не могли бы вы вставить командную строку?   -  person Xiè Jìléi    schedule 08.04.2011
comment
Пожалуйста, ознакомьтесь с ответом на странице stackoverflow.com/a/51841035/2457251, если вам нужна дополнительная информация. Например, вы можете добавить в файл .sh команду rm $f, mv $f или добавить любую другую команду, если хотите.   -  person sflr    schedule 14.08.2018


Ответы (5)


ты пробовал:

find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -exec rm {} \;

or

find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -delete

или запустить второй поиск после разархивированного

find . -depth -name '*.zip' -exec rm {} \;   
person ggiroux    schedule 08.04.2011
comment
Я получаю find: paths must precede expression: /usr/bin/unzip. - person Ben; 08.04.2011
comment
Ах! Второй вариант работает идеально. -delete, как же я вас не знал! Один из основных критериев, который я, конечно, забыл упомянуть, заключается в том, что распаковка и удаление должны происходить подряд, так как диск недостаточно велик, чтобы распаковать все, а затем вернуться к удалению. Большое спасибо! - person Ben; 08.04.2011
comment
Предупреждение: третий вариант НЕ работает, когда в zip-файлах есть другие zip-файлы. - person flolo; 08.04.2011
comment
-1 предупреждение, что эта команда извлечет все zip-файлы в ваш рабочий каталог. Было бы лучше, если бы zip-файлы оставались на пути, по которому они были найдены. - person cmcginty; 20.05.2015
comment
Обратите внимание, что если у вас есть более одного предложения (i)name, они должны быть заключены в круглые скобки: find \( -iname "*.zip" -o -iname "*.7z" \) -execdir 7z x {} \; -delete - person Luca Citi; 17.01.2019

спасибо за вторую команду с -delete! мне очень помогло.. всего 2 (возможно, полезных) замечания с моей стороны:

- пришлось использовать '.zip' вместо `.zip` в моей системе Debian

-используйте -execdir вместо -exec > это извлечет каждый zip-файл в его текущую папку, в противном случае вы получите весь извлеченный контент в каталоге, в котором вы вызвали команду поиска .

найти . -depth -name '*.zip' -execdir /usr/bin/unzip -n {} \; -удалить

THX & С уважением, Норд

person Nordmann    schedule 17.03.2012
comment
Вы можете добавить дополнительное примечание о том, что если у вас есть более одного предложения (i)name, они должны быть заключены в круглые скобки: find \( -iname "*.zip" -o -iname "*.7z" \) -execdir 7z x {} \; -delete. Также обратите внимание, что iname может быть лучше, поскольку оно также соответствует .ZIP. - person Luca Citi; 18.01.2019

Как упоминалось выше, это должно работать.

найти . -depth -name '*.zip' -execdir unzip -n {} \; -удалить

Однако обратите внимание на две вещи:

  • Параметр -n указывает распаковке не перезаписывать существующие файлы. Вы можете не знать, отличаются ли zip-файлы от целевых файлов с аналогичными именами. Тем не менее, -delete удалит zip-файл.
  • Если unzip не может разархивировать файл, скажем, из-за ошибки, он все равно может быть удален. Команда обязательно удалит его, если вместо -delete используется -exec rm {} \;.

Более безопасным решением может быть перемещение файлов после распаковки в отдельный каталог, который можно удалить, если вы уверены, что успешно извлекли все файлы.

person John D.    schedule 15.12.2013

Распаковать архивы в подкаталог на основе имени файла (../file.zip -> ../file/..):

for F in $(find . -depth -name *.zip); do unzip "$F" -d "${F%.*}/" && rm "$F"; done
person cmcginty    schedule 20.05.2015

У меня есть каталог, заполненный заархивированными CSV-файлами. Внешние процессы часто записывают на него новые заархивированные файлы. Я хочу распаковать и удалить оригиналы, как вы.

Для этого я использую:

    unzip '*.zip'
    find . | sed 's/$/\.zip/g' | xargs -n 1 rm 

Он работает путем поиска и раскрытия всех zip-файлов, находящихся в настоящее время в каталоге. Позже, после того, как он завершится, там также будут смешаны потенциально новые разархивированные новые файлы, которые еще не нужно удалять.

Поэтому я удаляю, находя успешно разархивированные файлы *.csv и используя sed для восстановления исходных имен файлов для удаления, которые затем передаются в rm с помощью команды xargs.

person Minkymorgan    schedule 31.03.2016