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

if ステートメント内でワイルドカード式を使用して「.gz」ファイル名拡張子をチェックする場合は、次のような式を使用します。

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出力として が生成され、2 番目の例では が生成されます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)プレーンな変数ではなく配列を割り当てますが、この場合、それは意味がありません。

4 行目の にはecho -n "Enter File Directory:"$gzip_file、変数 に関する同じ問題がありますgzip_file。また、 はecho -n予測不可能であり、コマンドのバージョンによって動作が異なりますecho。改行なしで文字列を印刷するには、 を使用する方がはるかに適切ですprintf "%s" "string to print"が、この場合は、後で説明するより適切なオプションがあります。

5行目の はread $gzip_file、ユーザー入力を変数 に読み込むことを意図しているように見えますgzip_fileが、実際にはそうではありません。シェルでは、$変数名の前に を置くと、取得変数の現在の値。ここではセットそのため、$off:を省略する必要があります。しかし、それは私が行うことではありません。プロンプト ( 4 行目) をコマンドの一部としてread gzip_file含めます。echoread

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

その他の 3 つの注意事項:DATEシェルや一部のユーティリティにとって特別な意味を持つさまざまな大文字の環境変数との競合を避けるため、などの大文字の変数名の使用はお勧めしません。また、予期しない解析エラーを避けるため、変数参照は常に二重引用符で囲みます ("$var"つまり、 ではなく を使用します)。また、句にはテストがないため、 の使用は意味がありません (また、の後にがあると構文エラーになります)。$varelseelse [[ some test ]]thenelse

したがって、スクリプトが何をするかを理解している場合は、スクリプトの先頭を次のように置き換えることをお勧めします。

#!/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 パターンが必要な場合)、ワイルドカード パターンは .gz ファイルのみをリストするため、 に .gz 拡張子があるifかどうかを確認する必要はありません。$gzip_file

もう一つ注意点:シェルチェックシェル スクリプトの基本的なエラーを指摘するのに非常に役立ちます。私が指摘した内容の多くは見逃されましたが、外れたエラーthen(最初は見逃していました) は見つかりました。

関連情報