Может ли оболочка зациклить все файлы в каталоге? - PullRequest
6 голосов
/ 25 апреля 2010

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

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

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

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

Ответы [ 5 ]

2 голосов
/ 25 апреля 2010

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

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

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

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

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

for i in $dir; do
  pushd $i
  unzip *.zip
  rm -rf *.zip
  popd
done
1 голос
/ 25 апреля 2010

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

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

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

1 голос
/ 25 апреля 2010

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

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

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

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

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

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

0 голосов
/ 26 апреля 2010

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...