単純なbashスクリプトが機能しない

単純なbashスクリプトが機能しない

このスクリプトは、コマンドラインから引数として名前が付けられたすべてのファイルをユーザーのホームディレクトリにコピーする必要があります。ファイルが提供されていない場合、スクリプトは読み取りを使用してファイル名を要求し、応答に指定されたすべてのファイル名をユーザーのホームディレクトリにコピーする必要があります。

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

文字列形式でパラメータを指定すると機能します。しかし、「$ 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を使用するときも使用できます[[ ... ]]。内部コマンドなので、一般的には良いです(この場合、コマンドは引用符なしで機能する必要がありますが、引用符を保持しても問題にならず、大丈夫です)。

(PS:このスクリプトにはまだ多くのバグがあります。ベストプラクティスとは離れていて、誰かがこれを教えるのを見て本当にショックを受けました。残念ながらbashを教える基準が本当に低いようです。理解するまでは複雑なので、正しく学ぶ方法についてのより良いアドバイスがあるかどうかわかりません)。☹️

答え3

このreadコマンドは変数を受け入れますが、変数の値を引用しました。

 #correct syntax
 read variable
 #wrong syntax
 read $variable

$variable値で、variableスクリプトの先頭で値は設定されていません/nullです。

関連情報