Подстановочный знак не интерпретируется в операторе if

Подстановочный знак не интерпретируется в операторе if

В настоящее время я пишу следующий скрипт. Код ищет в определенном каталоге имя файла, введенное пользователем. Сначала скрипт проверяет, является ли входной файл gzip, если да, он запускает соответствующие проверки. Если файл не сжат gzip, он отвечает несовместимым текстом файла.

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

#!/bin/bash
DATE=$(date +%Y-%m-%d)
L0_Report_Generator=("/home/ubuntu/$gzip_file")
echo -n "Enter File Directory:"$gzip_file 
read  $gzip_file
for gzip_file in {$L0_Report_Generator}; do
  if [[ $gzip_file = "test_sub"*"gz" ]] #Check file extension for gzip compression
      then
         gunzip $gzip_file
         echo "file Level 0 QC Check"
         echo ${DATE}
         echo "File Header"
         cat $gzip_file | head
         echo "Total Records"
         cat $gzip_file | wc -l
         echo "File Unique Records Size"
         cat $L0_Report_Generator | sort -u | wc -l
         rm $gzip_file 
    else [[ $gzip_file != "test_sub"*"gz" ]] #If file is anything other than .gz and csv - rort will not run
       then
         echo "incompatible file"
         fi
done

решение1

Если вы хотите проверить расширение имени файла «.gz», используя подстановочное выражение внутри оператора if, то вам следует использовать выражение, подобное следующему:

if [[ "${gzip_file}" = *.gz ]]; then echo true; else echo false; fi

Вот как вы можете это проверить:

if [[ "file.gz" = *.gz ]]; then echo true; else echo false; fi

и:

if [[ "file.txt" = *.gz ]]; then echo true; else echo false; fi

Первый пример выводит trueна экран , а второй пример выводит false.

Теперь давайте посмотрим на ваш код. Вместо этого ваш оператор if имеет следующее условное выражение:

[[ $gzip_file = "test_sub"*"gz" ]]

В частности, вы включаете "test_sub" как подстроку в ваш шаблон сопоставления. Попробуйте удалить это.

решение2

В дополнение к тому, что сказал @igal о проверке расширения файла, у вас много ошибок в синтаксисе и использовании переменных. Начните со строки 3:

L0_Report_Generator=("/home/ubuntu/$gzip_file")

Переменная gzip_fileеще не установлена, поэтому $gzip_fileбудет заменена ничем, когда оболочка ее расширит. Кроме того, скобки в var=(something)назначают массив вместо простой переменной, и в этом случае это не имеет никакого смысла.

Четвертая строка, echo -n "Enter File Directory:"$gzip_file, имеет ту же проблему с переменной gzip_file. Она также имеет проблему, которая echo -nнепредсказуема и будет делать разные вещи в разных версиях команды echo. Чтобы напечатать строку без перевода строки, вам гораздо лучше использовать printf "%s" "string to print", но в этом случае есть лучший вариант, к которому я вернусь через минуту.

Пятая строка, read $gzip_file, по-видимому, предназначена для чтения пользовательского ввода в переменную gzip_file, но это не то, что она делает. В оболочке, когда вы ставите $перед именем переменной, этополучаеттекущее значение переменной. Здесь вы хотитенаборэто, поэтому вы должны оставить $off: read gzip_file. Но это не то, что я бы сделал. Я бы включил приглашение (которое вы echoв строке 4) как часть readкоманды:

read -p "Enter File Directory:" gzip_file

Хорошо, теперь строка 6:

for gzip_file in {$L0_Report_Generator}; do

Похоже, это настройкаgzip_file снова(заменяя значение, которое мы только что readв него вставили). Вы на самом деле пытаетесь установить gzip_fileздесь, и предыдущие ссылки на переменные действительно должны были быть другой переменной (может быть, gzip_dirвместо этого)?

Кроме того, эта inчасть не имеет никакого смысла. Я думаю, вы пытаетесь использовать переменную L0_Report_Generator, но в этом случае открывающая скобка должна идтипослезнак доллара. Но это тоже не совсем имеет смысл, потому что ${L0_Report_Generator}это будет (если я правильно понимаю, что это должно делать) просто путь к каталогу. for ... inне перебирает содержимое каталогов, а перебирает списокслова, например for var in word1 word2 "word 3 which has several spaces in it" word4; do. Если вы хотите получить список файлов в каталоге, вам нужно использовать подстановочный знак, например for var in dir/*; do-- оболочка расширит шаблон файла, содержащий подстановочные знаки, в список соответствующих файлов, каждый из которых будет рассматриваться как слово, и выполнит итерацию по ним. У вас также есть возможность ограничить совпадения файлами с определенным расширением, включив его в шаблон, например dir/*.gz.

Еще три замечания: я рекомендую не использовать заглавные имена переменных, например DATE, чтобы избежать конфликтов с различными переменными окружения, написанными заглавными буквами, которые имеют особое значение для оболочки или некоторых утилит. Кроме того, всегда заключайте ссылки на переменные в двойные кавычки (т. е. используйте "$var"вместо просто $var), чтобы избежать неожиданных странностей синтаксического анализа. И в elseпредложении нет проверки, поэтому использование else [[ some test ]]не имеет смысла (а наличие thenпосле elseявляется синтаксической ошибкой).

Итак, если бы я понимал, что должен делать скрипт, я бы рекомендовал заменить начало скрипта на:

#!/bin/bash
date=$(date +%Y-%m-%d)    # Note lowercase variable
read -p "Enter File Directory:" gzip_dir
L0_Report_Generator="/home/ubuntu/$gzip_dir"

for gzip_file in "${L0_Report_Generator}"/*.gz; do

...И затем (если шаблон .gz, указанный выше, — это то, что вам нужно), вам не нужно ifпроверять, $gzip_fileимеет ли файл расширение .gz, поскольку подстановочный шаблон будет перечислять только файлы .gz.

Еще одно замечание:shellcheck.netочень полезно для указания основных ошибок в скриптах оболочки. Он пропускает многое из того, на что я указал, но ловит отвлекающие then(которые я изначально пропустил).

Связанный контент