現在、以下のスクリプトを書いています。このコードは、ユーザーが入力したファイル名の特定のディレクトリを検索します。スクリプトはまず、入力ファイルが 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
含めます。echo
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
。
その他の 3 つの注意事項: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 パターンが必要な場合)、ワイルドカード パターンは .gz ファイルのみをリストするため、 に .gz 拡張子があるif
かどうかを確認する必要はありません。$gzip_file
もう一つ注意点:シェルチェックシェル スクリプトの基本的なエラーを指摘するのに非常に役立ちます。私が指摘した内容の多くは見逃されましたが、外れたエラーthen
(最初は見逃していました) は見つかりました。