2012-05-16 2 views
3

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

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

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

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

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

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

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

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

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

+2

Если в ваших именах есть пробелы, ваше решение взорвется. Этот вопрос задается здесь 2-3 раза в неделю. Потратьте немного времени и найдите '[bash] find while' (не используйте для циклов). Удачи. – shellter

+0

@shellter, имена папок программно генерируются скриптом и не имеют имен файлов. В то время как ваша точка была бы действительной в противном случае, она действительно не вступает в игру в этой ситуации. – Jason

+0

@shelter - использование while предотвратит его взорвание, если в имени файла есть пробел, но нет, если в имени есть новая строка (которая действительна). – jordanm

ответ

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 
3

Я рекомендую использовать подоболочку для переключения Справочники:

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

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

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

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

+0

Не работает с каталогами, содержащими пробелы в имени. – jordanm

+0

Хорошо пятнистый; мой последний абзац касается именно этой проблемы. –

2

На самом деле нет никаких причин для cd в каталоге для запуска команды ls. Должно работать:

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

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

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

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

Смежные вопросы