Официальная возможность получить лицензионный софт бесплатно.
Giveaway of the Day
Это не реклама!

Щелкните для получения прогноза по Биробиджану


среда, 18 мая 2016 г.

bash: цикл по именам файлов с пробелами

Цикл FOR по списку в bash работает хорошо. До тех пор, пока внутри элементов списка не появляются пробелы - вместе с пробелами появляются и проблемы: каждое слово в составе элемента списка рассматривается отдельно, и если попадается файл вроде "цикл не работает", то for будет выполнен для него три раза - для "цикл", для "не" и для "работает", что не есть хорошо.

Понадобилось мне сконвертировать несколько файлов из png в jpg. И как раз наступил на упомянутые грабли (имена файлов настоящие и опечатки в слове "внутренний" нет):

$ for a in `ls -Q litb\ внтуренний\ счет*.png`; do echo "$a"; done
"litb
внтуренний
счет2.png"
"litb
внтуренний
счет.png"

Разумеется, convert обиделся и сказал, что не знает, что я от него хочу, получив на входе такую абракадабру.

Несколько различных способов решения я нашел здесь. Выбрал простейший: изменить значение переменной IFS, отвечающей за разделитель слов. По умолчанию IFS=" " (пробел), что совершенно не подходит для моей задачи. Поэтому родилась такая уродливая команда. Уродливая она, правда, для короткого цикла - для обработки двух файлов быстрее получилось бы два раза запустить convert, подсунув ему нужные имена. Но в случае обработки большого списка файлов она очень даже уместна.

$ oldifs="$IFS"; IFS=$(echo -en "\n\b"); for a in $(ls litb\ внтуренний\ счет*.png); do nam=$(basename -s png "$a")jpg; convert "$a" "$nam"; done; IFS="$oldifs"

Теперь подробнее.


  1. сохраняем старое значение IFS
  2. присваиваем IFS новое значение
  3. цикл по результатам команды ls
  4. чтобы не возиться с кавычками, новое имя файла формируем в переменной nam
  5. возвращаем исходное значение IFS

Немного о команде basename. С ключом -s она отсекает от имени файла указанное расширение, суффикс, в данном случае - "png"

Комментариев нет:

Отправить комментарий

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