Linux bash script: использование ls с glob и получение вывода в переменной не работает - PullRequest
0 голосов
/ 13 декабря 2018

На моем компьютере с CentOS 7 у меня есть папка, которая содержит 2 файла с именами, такими как:

myapp-nightly__v3.0-SNAPSHOT__b59__lite.zip
myapp-nightly__v3.0-SNAPSHOT__b59.zip

Эти файлы стираются и генерируются каждую ночь, а число после "b" (впример выше, 59), увеличивается.

Я хочу иметь файл сценария bash, в котором я могу получить в переменной имя файла, в котором нет «_lite»(в приведенном выше примере это было бы «myapp-nightly__v3.0-SNAPSHOT__b59.zip»)

Итак, я сначала попробовал «ls» с глобализацией в терминале, чтобы увидеть, как это работает:

ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip

Это корректно выводит "myapp-nightly__v3.0-SNAPSHOT__b59.zip".

Затем я попытался создать простой скрипт bash, который запускает указанную выше команду и сохраняет ее вывод в переменной:

#!/bin/bash
MYAPP_KIT_FULL_PATH=$(ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
echo "MYAPP_KIT_FULL_PATH=$MYAPP_KIT_FULL_PATH"

Это дает мне следующую ошибку:

./test.sh: command substitution: line 3: syntax error near unexpected token `('
./test.sh: command substitution: line 3: `ls myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)'

Итак, мой вопрос, как правильно выполнить такую ​​команду "ls" в скрипте bash и сохранить ее выводв переменную?Разве это не работает в bash из-за символов глобуса?

Дополнительные замечания:

  • Я знаю, что в сообщении об ошибке указано "строка 3", но я почти уверен, что оно относится к строке2 (строка 3 просто делает эхо).Даже если я полностью удалю строку 3 из сценария (чтобы в сценарии было только 2 строки), он все равно выдает ошибку о строке 3

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Вы используете выражение расширенного глобуса (подстановочный знак), но ошибка указывает, что у вас не включены расширенные глобусы.Вы можете добавить shopt -s extglob в начале.Но вы также не должны анализировать вывод ls.

. Есть несколько вариантов сделать это "правильно" в bash.@ Аарон уже показал, как использовать find, поэтому я дам пару вариантов чистого bash.Во-первых, вы можете просто использовать пустое подстановочное выражение (без ls) и записать результат в массив:

#!/bin/bash
shopt -s extglob
myapp_kit_full_paths=(myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip)
# Operate on just the first match:
unzip "${myapp_kit_full_paths[0]}"
# Operate on *all* matches (in case there are several):
for file in "${myapp_kit_full_paths[@]}"
    unzip "$file"
done

(Кстати, обратите внимание, что здесь я использовал имя переменной в нижнем регистре. Есть кучаимен всех заглавных букв со специальным значением, и случайное использование одного из них может вызвать проблемы, поэтому имена переменных в нижнем и смешанном регистре безопаснее для ваших собственных целей.)

Другой вариант - просто расширитьвыражение glob непосредственно в операторе for:

#!/bin/bash
shopt -s extglob
for myapp_kit_full_path in myapp-nightly__v3.0-SNAPSHOT__b+([0-9]).zip
    unzip "$myapp_kit_full_path"
done
0 голосов
/ 13 декабря 2018

Вы можете использовать find:

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip'

Чтобы разархивировать целевой файл в вашем текущем каталоге:

find dir -maxdepth 1 -name 'myapp-nightly__v3.0-SNAPSHOT__b*.zip' -not -name '*lite.zip' -exec unzip {} \;
...