私の非常に原始的なシェルスクリプトは2つのパラメータを使います。 1つ目は場所、2つ目は削除する必要があるファイルの数です。何らかの理由で例3のようなパラメータを与えたのにファイルが1つだけ削除されますね。パスワード:
#!/bin/bash
for i in {0..$2}
do
find $1 -type f | head -1 | xargs rm
done
修正する このコードは何らかの理由で2つのファイルを削除するようです。
#!/bin/bash
for i in eval {0..$2}
do
find "$1" -type f | head -1 | xargs rm
done
答え1
優先順位の問題です。角かっこ拡張内の変数は、角かっこが評価されるため解釈されません。今後変数が展開されます。これを説明するには、次のコマンドを実行します。
$ var=3
$ set -x
$ echo {0..$var}
+ echo '{0..3}'
{0..3}
ご覧のとおり、 に拡張さecho {0..$var}
れているため、echo '{0..3}'
リテラル文字列は期待したものとは{0..3}
異なります。0 1 2 3
この問題を解決する1つの方法は、次の方法を使用することですeval
。
$ eval echo {0..$var}
+ eval echo '{0..3}'
++ echo 0 1 2 3
0 1 2 3
したがって、スクリプトを次のように変更できます。
#!/bin/bash
for i in $(eval echo {0..$2})
do
find "$1" -type f | head -1 | xargs rm
done
しかし、これは危険で醜いことです。これがより良いでしょう:
#!/bin/bash
for((i=0;i<=$2;i++))
do
find "$1" -type f | head -1 | xargs rm --
done
いくつかの基本的なセキュリティテストがあり、任意のファイル名(名前に改行を含むファイルを含む)を処理できるより良いバージョン(GNUツールを使用している場合)は次のとおりです。
#!/bin/bash
if [[ $# -ne 2 ]]; then
echo "We need 2 arguments!"
exit
fi
if [[ ! $2 =~ ^[0-9]+$ ]]; then
echo "The second argument ('$2') must be a number!"
exit;
fi
for((i=0;i<=$2;i++))
do
find "$1" -type f -print0 | head -z -n 1 | xargs -0 -I {} rm -- {}
done