引数を読み取り、それがディレクトリ、通常ファイル、実行可能ファイル、またはシンボリック リンク ファイルであるかどうかをテストし、ターミナルに出力する BASH スクリプトを作成しようとしています。
スクリプトを実行するときに「./myscript.bash *」を使用して確認しましたが、予測された結果は得られませんでした。ホーム ディレクトリ内のすべての項目の名前が「見つかりません」とのみ表示されます。例:
「デスクトップが見つかりません」「ダウンロードが見つかりません」など、ホーム フォルダーにディレクトリがあるにもかかわらず表示されます。何が間違っているのか、誰か知っていますか?
#!/bin/bash
for i in $*; do
if [ -d “{$i}” ]; then
echo “${i} (Directory)”;
elif [ -x “{$i}” ]; then
echo “${i} (Executable)”;
elif [ -h “{$i}” ]; then
echo “${i} (Symbolic)”;
elif [ -f “{$i}” ]; then
echo “${i} (Ordinary)”;
else
echo “${i} not found”
fi
done
答え1
単純なスクリプトをデバッグする際の第一のルール:
うまくいかない場合は、エコーしてみてください。
この場合:
for i in $*; do
echo "testing if “{$i}” exists"
if [ -d “{$i}” ]; then
echo “${i} (Directory)”;
<... rest of the script ...>
すぐに返答が次のようになることがわかります。
testing if “{Downloads}” exists
...
つまり、テストは「{Downloads}」(smartquotes-accolade open-Downloads-accolade close smartquotes) が存在するかどうかです。
そのディレクトリはおそらく存在しないでしょう。
スマートクォートは、シェルスクリプト初心者にとっては見落としがちなものです。Bash (および他のほとんどのシェルも同様) は、クォートの使用に非常に慎重です。一重引用符 ( '
) は二重引用符 ( "
) とは意味が異なります。バッククォートも意味が異なります。スマートクォートは、母親が教えてくれたもので、何もしません (ジェファーソン エアプレインの引用を許していただければ)。"
ここでは、変数の展開を可能にするため、二重引用符 ( ) が絶対に必要です。
次は と です{
。}
ではecho
、次のことを記述します。
echo “${i} not found”
しかし、ではif
違います{$i}
。違いを見つけてください。
if [ -d "${i}" ]; then
それはうまくいっただろう。
カミル氏はコメントの中でこう書いている。
ほとんど欲しいものはありません
$*
。むしろ、ほとんど常に欲しいものなのです"$@"
。
$*
そして彼は正しい。との違いについては何ページも説明されている"$@"
が、その違いを示す最も簡単な方法は次のようになる。
#!/bin/bash
echo ------------------
echo '$*'
for i in $* ; do echo $i ; done
echo ------------------
echo '"$@"'
for i in "$@" ; do echo $i ; done
echo ------------------
(私はこのスクリプトを と呼びa
、次のように実行します。
bash a 'plop 123' plop 123
------------------
$*
plop
123
plop
123
------------------
"$@"
plop 123
plop
123
------------------
答え2
@ljm はまさにその通りです。私がそれを拡張するために言いたいのは、常に望ましい結果をエコーし、その周りに優れた機能を構築することだけです。
つまり、まずはそれが機能することを確認し、それからより良く機能するようにするのです