Переменные диапазона в цикле for, определяемые пользователем

Является ли использование только find exec строгим требованием? Я бы предпочел зациклить результаты find и объединить их с помощью удобного для работы со строками инструмента, такого как awk :

for ii in $(find . -name "*.zip")
do
    mv $ii $(echo $ii|awk -F/ '{print "someString_" $2 "_" $4 "+" $6}')
done

(Замените mv на ) echo mv для целей тестирования.)

Примечание: параметр -F / в awk устанавливает / в качестве разделителя вместо пробелов и табуляции.

Обновление

Как было предложено в комментариях Стефана, вероятно, было бы разумнее и надежнее настроить оператор split + glob (подробнее об этом здесь ) заранее:

IFS=$'\n'
set -f

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

Не забудьте после этого переключить их на предыдущие настройки, если вы не хотите потом рвать волосы из-за «странного» поведения… Предполагая, что вы не настраивали эти настройки:

unset IFS
set +f

3
27.09.2017, 14:23
2 ответа

Проблема в том, что раскрытие фигурной скобки происходит до раскрытия переменной. Как поясняется вman bash:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.

Это означает, что когда у вас есть что-то вроде $var, которое содержит {1..3}, и выполняете echo "$var", оболочка ищет возможные раскрытия фигурных скобок перед расширением переменной до ее значения. Поскольку фигурные скобки находятся в переменной, это означает, что в этот момент оболочка не видит фигурных скобок, поэтому раскрытие скобок не выполняется.

Одним из обходных путей может быть evalпеременная, если она представляет собой диапазон. Добавьте эти строки перед циклом for:

if [[ $RANGE =~ ^[0-9]+\.\.[0-9]+$ ]]; then
        RANGE=$(eval echo {$RANGE})
fi

Теперь, в более общем плане, рекомендуется избегать использования имен переменных ЗАГЛАВНЫМИ БУКВАМИ в сценариях оболочки. Переменные среды обычно пишутся с заглавной буквы, и это может привести к путанице, если вы используете то же имя, что и определенная переменная среды. Поэтому используйте имена переменных в нижнем регистре, чтобы быть в безопасности.

Кроме того, эта программа очень утомительна при отладке и в равной степени утомительна в использовании. Не запрашивайте у пользователя ввод во время выполнения! Вместо этого измените свой сценарий и заставьте его принимать аргументы. Ввод значений сложный, раздражающий, подверженный ошибкам и не может быть автоматизирован.

3
27.01.2020, 21:30

Установите для своей оболочки значение ksh, и этот код должен работать.

#!/usr/bin/ksh

-1
27.01.2020, 21:30

Теги

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