Цикл оболочки может разархивировать все файлы в каталоге?

Я видел циклы для разархивации всех zip-файлов в каталоге. Однако, прежде чем я выполняю это, я удостоверился бы, что я собираюсь выполнить, будет работать правильно:

for i in dir; do cd $i; unzip '*.zip'; rm -rf *.zip; cd ..; done

В основном я хочу, чтобы это посмотрело на вывод "dir", видят все папки, для каждого CD каталога в него, разархивировали все архивы zip, затем удаляют их, затем CD назад и делают это снова, пока больше нет.

Это - что-то, что я должен сделать в единственной команде, или я должен рассмотреть выполнение этого в Perl?

6
задан brian d foy 25 April 2010 в 22:46
поделиться

5 ответов

частично протестировано:

find . -type d -exec  sh -c "cd \"{}\" ;  unzip \"*.zip\" ; rm \"*.zip\"  "  \;

выполняет цепочку cd / unzip / rm для каждого подкаталога.

1
ответ дан 17 December 2019 в 02:25
поделиться

В целом с вами все должно быть в порядке. Для отладки просто поставьте перед всеми командами в цикле префикс . Echo сообщит вам, как расширяются переменные. Вы также всегда можете использовать rm -i , чтобы запросить его, вместо того, чтобы заставлять rm продолжать что-либо с помощью -f .

Одиночные кавычки в вызове unzip будут распаковывать только файлы с именами *. Zip , то есть * не будет расширяться. Вместо этого используйте двойные кавычки (или вообще не используйте кавычки).

Теперь ваш цикл предполагает, что все каталоги $ i находятся непосредственно под текущим. Более общим решением было бы использование стека каталогов ( pushd и popd );

for i in $dir; do
  pushd $i
  unzip *.zip
  rm -rf *.zip
  popd
done
2
ответ дан 17 December 2019 в 02:25
поделиться

Используйте * , чтобы получить содержимое текущего каталога:

for i in *; do cd "$i"; ...etc... ; done

Вы также должны убедиться, что что-то является каталогом, прежде чем пытаться вставить в него cd. В bash это делается следующим образом:

if [ -d "$i" ]; then ...etc... ; fi

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

Я думаю, что это раздвигает предел того, что разумно делать одной строкой. Поместите его в сценарий оболочки и отформатируйте в несколько строк.

1
ответ дан 17 December 2019 в 02:25
поделиться

Если вы хотите знать, сработает ли что-то, но опасаетесь разрушительных последствий, делайте постепенно:

Убедитесь, что вы получили нужные файлы:

for i in dir; do cd $i; echo $i; cd ..; done

Убедитесь, что вы можете разархивировать файлы, прежде чем удалять файлы:

for i in dir; do cd $i; unzip '*.zip'; cd ..; done

И, прежде чем делать полную запись, сделайте резервную копию вашего каталога.

0
ответ дан 17 December 2019 в 02:25
поделиться

Несколько моментов, добавляющих к тому, что сказали другие:

  • Если вы поместите параметр в одинарные кавычки, как в '*. Zip' , оболочка не будет использовать подстановочные символы, а unzip попытается обработать архив, который буквально называется *. zip
  • Не используйте -r в качестве параметра для rm , если вы просто хотите удалить отдельные файлы. Это просто излишне опасно, поскольку любое рекурсивное удаление подкаталогов, вероятно, не предназначено.
  • Вы должны проверить код возврата unzip и удалить zip-файл только в том случае, если распаковка прошла успешно (например, вы можете сказать , если unzip * .zip; затем rm * .zip; fi или даже использовать явный цикл for для обработки zip-файлов один за другим)
2
ответ дан 17 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: