このスクリプトは、コマンドラインで引数として名前が指定されているすべてのファイルをユーザーのホーム ディレクトリにコピーします。ファイルが指定されていない場合、スクリプトは read を使用してファイル名を要求し、応答で指定されたすべてのファイル名をユーザーのホーム ディレクトリにコピーします。
if [ -z $1 ]
then
echo provide filenames
read $FILENAMES
else
FILENAMES="$@"
fi
echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
cp $i $HOME
done
引数を文字列として指定すると、動作します。ただし、「read $FILENAMES」として指定すると、動作しません。
メンターはレッスンで同じ解決策を示しましたが、それがどのように機能するかは示しませんでした。
更新ファイル名を引数として入力すると、空の文字列が返され、$HOMEの場所にファイルがコピーされませんでした
[dmytro@oc1726036122 ~]$ cd Desktop/
[dmytro@oc1726036122 Desktop]$ . totmp
provide filenames
one two
the following filenames have been provided:
the following filenames have been provided:
[dmytro@oc1726036122 Desktop]$
答え1
はread
変数を読み取るのではなく、宣言します。簡単に言うと、$
から を削除すればread
準備完了です。
if [ -z $1 ]
then
echo provide filenames
read FILENAMES
else
FILENAMES="$@"
fi
echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
cp $i $HOME
done
編集:スクリプトを実行するためにsource
( ) コマンドを使用していることがわかりました。.
[dmytro@oc1726036122 Desktop]$ . totmp
この特定のスクリプトでは問題ないかもしれませんが、複雑なスクリプトでは絶対にそうしないでください。そうしないと、そのスクリプトの変数や関数をシェルに取り込むことになります。bash totmp
答え2
あなたを妨げている問題は、read
コマンドが正しくないことです。コマンドに渡される引数は変数名である必要があるため、 なしで渡す必要があります$
( は$
変数の内容を展開しますが、その時点では空なので、結果はread
変数名が渡されない になります)。
read FILENAMES
最初のコマンドライン引数が存在しないかどうかのチェックには、別の問題があります。引数が存在しない場合は、$1
何も展開されません (空の文字列ではありません)。この場合、引数が有効ではないはずな[
ので、コマンドで問題が発生する可能性があります。つまり、その変数を引用符で囲む必要があります。[ -z ]
[ -z "" ]
if [ -z "$1" ]
bash を使用している場合は、 を使用することもできます[[ ... ]]
。これは内部コマンドなので、通常はこちらの方が適しています (その場合、このコマンドは引用符なしでも機能しますが、引用符を付けたままでも問題はありませんし、見栄えも良くなります)。
(追記: このスクリプトには他にも多くの問題があり、ベストプラクティスからは程遠いので、誰かがこれを教えるのを見ると本当に驚きます。残念ながら、bash を教えるハードルは非常に低く、実際によく理解するまでマニュアルは非常に複雑なので、適切に学習する方法について、私にもより良いアドバイスがあるかどうかわかりません。)☹️
答え3
コマンドread
は変数を取りますが、すでに変数の値を参照しています。
#correct syntax
read variable
#wrong syntax
read $variable
$variable
は の値でありvariable
、スクリプトの先頭ではこれは未設定/空です。