Bashスクリプトの一般的な問題[閉じる]

Bashスクリプトの一般的な問題[閉じる]

私が作業している最初の部分は、bashシェルで利用可能なすべてのコマンドのテキストファイルのコピーを含むcommand_manualsというフォルダを作成することです。ファイル名はコマンド名自体です。目標を達成するスクリプトに影響を与えないいくつかの例外エラーメッセージを除いてこの部分を得ることができましたが、最も深刻な問題を最初に議論することを好むので、今はそのままにします。

利用可能なマニュアルを持っていない人はまだ空のテキストファイルを持っています。これは2番目の部分の目標につながります。この「0サイズのテキストファイル」を削除し、後で使用したい単一のリストをコンパイルします。 apt-updateを実行するたびに、「Undocumented man 7」をチェックする部分と他の人は、よく知られているパターン検索パッケージの1つを使用して、マニュアルにないra、ra、raコマンドに新しいものが追加されていることを確認します。とにかく重要ではありません。 2番目の部分のドラマを通過するまで、これまでサイズが0のフォルダ内容のサブセットのみを印刷するforループにif条件を正常に作成しましたが、この内容を再度再生しようとすると、デフォルトで「then」と「fi」の間のコマンドをエコーすると、空のファイルが削除され、問題が発生します。

しかし、それはまた私が見つけた別の奇妙な点に関連する追加の質問をもたらしました。それは私が望む方法で動作するデフォルトのテンプレートスクリプトに標準#!/ bin / bashがありません。私の.shスクリプト行、なぜ?

template_for_if_delete.sh

TOTALnum=$(wc -l < filesizes.txt);
for i in `seq 1 $TOTALnum`;
do
size=$(sed -n ''$i','$i'p' filesizes.txt)
if [ $size -eq 0 ];
then
echo $(sed -n ''$i','$i'p' filenames.txt);
fi
done;

これまで実際2番目の作業のためのスクリプト:

パート2.sh

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ $size -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

出力を生成します(上記のforループで定義された回数だけ繰り返されます)。

Try 'stat --help' for more information.
./secondpart.sh: line 9: [: -eq: unary operator expected
./secondpart.sh: line 8: x86_64-linux-gnu-gold.txt: command not found
stat: missing operand

次に、ifステートメントの変数 "size"を複雑なパラメータ拡張に変更しました。

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ ${#size} -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

関連のないランダムなアイテムを削除したいかどうかを尋ねる関連出力が生成され、その時点で私は大丈夫だと判断しました。私に役立つVMを台無しにする前に質問を投稿することをお勧めします。良かった:

./secondpart.sh: line 8: filenames.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file-roller.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information./code>
./secondpart.sh: line 8: filesizes.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: cannot remove adammvirtual/Win10UbuntuVM001_apt_sources_file.txt':
 No such file or directory
rm: cannot remove '/home/adamvirtual/mapfile.txt': No such file or directory
rm: remove write-protected regular file '/usr/share/doc/alsa-base/driver/Procfile.txt.gz'?

プロンプトを終了するにはctrl+を押します。C

ベストアンサー1

問題は./secondpart.sh: line 8どちらを設定する必要があるかです$filename

statそして議論がrmあったので、彼らは文句を言いました。$filenameこれらのエラーは後続のエラーです。

したがって、8行を修正する必要があります。

後続のエラーを回避するには、ほぼ常にset -euo pipefail最初のエラーでスクリプトを終了してスクリプトを開始する必要があります。


ただし、全体的にスクリプトが複雑すぎてwcループを使用するため、正しいアプローチではありませんforsedファイルを1行ずつ読み込む

ファイルサイズが0であることを確認するために使用する代わりに、stat -c %s次のものを使用できます。ファイルテスト演算子 -s、正確にします(実際にファイルサイズが次の場合は逆の場合を確認します)。いいえヤング)。

たとえば、次のようになります。

xargs -a filenames.txt -I{} sh -c '[ -s "$1" ] || rm -i "$1"' xargs-sh {}

または

readarray filenames < filenames.txt
for filename in "${filenames[@]}"; do
    [ -s "$filename" ] || rm -i "$filename"
done

または

while IFS= read -r filename; do
    [ -s "$filename" ] || rm -i "$filename"
done < filenames.txt

通常、ファイル名に改行が許可されるため、テキストファイルにファイル名を1行ずつ表示することはお勧めできません。代わりに、\0ファイル区切り文字として常にNULL文字()を使用する必要があります。

おすすめ記事