#bash #zip #unzip
Вопрос:
У меня есть много папок на FTP с их содержимым, и некоторые из них я должен время от времени обновлять. Я обновляю их, распаковывая полученные zip-файлы. Имена zip-файлов могут быть разными, но в zip всегда есть основная папка с точно таким же именем папки, которую следует обновить на FTP. Больше никаких других файлов/папок в ZIP-файлах, кроме основной папки с ее содержимым. Поэтому я написал простой скрипт ниже, чтобы обновить их:
unzip -o *.zip
rm -f *.zip
Проблема в том, что иногда в этих папках есть файлы, которые следует удалить — они больше не существуют в архивах с обновлениями. И я понял, что когда я распаковываю и перезаписываю, ничего не удаляется из того, что должно быть. Можно ли изменить этот скрипт, чтобы удалить целую папку перед распаковкой, чтобы быть уверенным? Правильное имя папки для обновления-это не имя zip, а имя основной папки в zip, и из-за этого я не знаю, как это решить. Я не мог найти существующего решения для этого. Кроме того, иногда я загружаю сразу много zip-файлов, а на FTP есть тысячи папок, поэтому было бы трудно написать одну команду для каждой отдельной папки.
Комментарии:
1. Почему вы упомянули FTP. Играет ли FTP какую-либо роль в вашей проблеме вообще или это была бы та же проблема, если бы вы получали zip-архивы из другого источника?
Ответ №1:
Вы можете использовать unzip
сопутствующую программу zipinfo
для просмотра содержимого zip-файлов. Добавьте шаблон */
в список только каталогов. Затем трубу xargs
, чтобы удалить их.
zipinfo -1 '*.zip' '*/' | xargs rm -rf 2>/dev/null
Это приведет к удалению всех существующих каталогов (которые совпадают в существующем zip-файле) сразу. Затем вы можете запустить остальную часть своего скрипта, чтобы извлечь новые.
Вы могли бы добавить cut -d / -f 1 | sort -u |
раньше xargs
, чтобы отфильтровать любые подкаталоги rm
, но это не должно иметь значения, даже если они есть.
xargs
разделяет строки пробелами, поэтому имя каталога, содержащее пробелы, может привести к удалению другого каталога. Для GNU xargs
вы можете добавить --delimiter='n'
, чтобы остановить это (есть также --null
, но zip
все равно обрезает новые строки в именах файлов). Вы также можете просто исключить каталоги, содержащие пробелы, с помощью конвейера grep -v '[[:space:]]'
.
Другой подход, который может быть полезен, заключается в обработке одного zip-файла за раз:
for zip in *.zip; do
dirs=$(zipinfo -1 "$zip" '*/') || continue
IFS=
Этот метод также подходит для пробелов. Разделение dirs
на массив просто означает rm
, что оно все равно будет успешным, если в архиве есть более одного каталога. Если zipinfo
это не удается, это, вероятно, означает, что архив поврежден или нечитаем, следовательно || continue
. Вы можете удалить это, если хотите попробовать извлечение в любом случае.
n' read -rd '' -a dirs<<<"$dirs"
rm -rf "${dirs[@]}"
unzip -o "$zip"
done
Этот метод также подходит для пробелов. Разделение dirs
на массив просто означает rm
, что оно все равно будет успешным, если в архиве есть более одного каталога. Если zipinfo
это не удается, это, вероятно, означает, что архив поврежден или нечитаем, следовательно || continue
. Вы можете удалить это, если хотите попробовать извлечение в любом случае.