Вопрос по bash – Скрипт оболочки для прохождения каталогов

3

Я работаю над проектом, который требует пакетной обработки большого количества файлов изображений. Чтобы упростить задачу, я написал скрипт, который создастn каталоги и переездm файлы к ним на основе пользовательского ввода.

Моя проблема в том, чтобы теперь понять обход каталога через скрипт оболочки.

Я добавил этот фрагмент в конце сценария сортировки, описанного выше.

dirlist=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  cd $dir
  echo $dir
  ls
done

Когда я запускал его в папке Pano2, которая содержит две внутренние папки, я всегда получал ошибку

./dirTravel: line 9: cd: Pano2/05-15-2012-2: No such file or directory

Однако после этого я получаю список файлов из указанного каталога.

В чем причина предупреждения? Если я добавлюcd ../ послеls Я получаю список папок внутри Pano2 /, но не сами файлы.

@ jason - это неправильный способ сделать это независимо. jordanm
@shellter, имена папок программно генерируются скриптом и не имеют имен файлов. Хотя в противном случае ваша точка зрения была бы действительной, в этой ситуации она действительно не вступает в игру. Jason
@shelter - использование while предотвратит его взрыв, если в имени файла есть пробел, но нет, если в имени есть новая строка (которая действительна). jordanm
если в ваших именах есть пробелы, ваше решение взорвется. Такого рода вопросы задают здесь 2-3 раза в неделю. Потратьте немного времени и найдите[bash] find while (не использовать для петель). Удачи. shellter
@jordanm: вы можете решить проблему перевода строки сfind ... -print0 | while IFS= read -d $'\0' -r file -- увидетьthis previous answer Gordon Davisson

Ваш Ответ

3   ответа
3

что вы заходите на два уровня глубиной, но возвращаетесь только на один уровень вверх. Попробуйте добавитьcd ../.. послеlsили используйтеpushd а такжеpopd вместо.

Например:

for dir in $dirlist
do
  pushd $dir
  echo $dir
  ls
  popd
done

Как указывает @shellter, если в этих каталогах есть пробелы, то что-то вроде этого может работать лучше:

find $1 -mindepth 1 -maxdepth 1 -type d | while read -r dir
do
  pushd "$dir"  # note the quotes, which encapsulate whitespace
  echo $dir
  ls
  popd
done
2

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

find "$1" -mindepth 1 -maxdepth 1 -type d -exec ls {} \;

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

find "$1" -mindepth 1 -maxdepth 1 -type d -exec bash -c 'cd "$1"; echo "$1"; ls' -- {} \;

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

3

в:

dirlist=$(find $1 -mindepth 1 -maxdepth 1 -type d)

for dir in $dirlist
do
  (
  cd $dir
  echo $dir
  ls
  )
done

Код внутри вложенной оболочки не повлияет на родительскую оболочку, поэтому он может изменить каталог в любом месте, не вызывая при этом никаких проблем с тем, как «вернуться».

Это сопровождается стандартным предупреждением о том, что весь процесс чреват, если имена ваших каталогов могут содержать пробелы, символы новой строки или другие неожиданные и неуклюжие символы. Если вы продолжаете с переносимым набором символов имени файла ([-_.A-Za-z0-9]Вы не столкнетесь с проблемами, как написано.

Хорошо подмечено; мой последний абзац охватывает именно эту проблему.
Не работает с каталогами, которые содержат пробелы в имени.

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