forループがディレクトリで実行されない理由

forループがディレクトリで実行されない理由

以下のスクリプトの最初の~のためループは期待どおりに実行されますが、2番目のループは実行されません。エラーは発生しません。スクリプトが中断されたようです。

HOME=/root/mydir

DIR=$HOME/var
DIRWORK=$HOME/Local

for f in $(find $DIR -type f); do

    lsof -n $f | grep [a-z] > /dev/null

    if [ $? != 0 ]; then
    echo "hi"       
    fi
done


for i in $(find $DIRWORK -type d -name work); do
    echo "2"
done

ベストアンサー1

あなたのスクリプトは危険な方法でコーディングされました。

まず、「/bash」と「/for」とマークしたので、Bashシェルを使用しているとします。

私の答えでは、私はこの素晴らしい言葉を引用します。強打ガイド、おそらくBashを学ぶのに最適なソースでしょう。

1)使用しないでくださいコマンドの置き換え誰でもクラス、引用符なし。これには大きな問題があります。引用符なしで拡張を使用すると、出力はパラメータに分割されます。

具体的にはこの過程を経ます$(find $DIRWORK -type d -name work)$(find $DIR -type f)噴射したがって、findファイル名にスペース、つまり「ファイル名」が含まれていると見つかった場合、Bashの単語分割の結果は、コマンドを繰り返すためのfor2つのパラメータ、つまり「ファイル」と「名前」のパラメータを渡します。この場合、実際に存在する場合は破損するのではなく、「ファイル:対応するファイルまたはディレクトリなし」と「名前:対応するファイルまたはディレクトリなし」をインポートすることをお勧めします。

2)通常、環境変数(PATH、EDITOR、SHELL ...)と内部シェル変数(BASH_VERSION、RANDOM ...)はすべて大文字です。他のすべての変数名は小文字でなければなりません。変数名は大文字と小文字を区別するため、この規則は誤って環境変数と内部変数を上書きするのを防ぎます。

$DIRWORKディレクトリはその規則を破って引用符も解放されているため、許可すると、DIRWORK='/path/to/dir1 /path/to/dir2'$ findDIRWORKは引用符が解放されると2つの異なるディレクトリが表示されます。引用符を使用するトピックはBashで非常に重要であるため、「二重引用符」を使用する必要があります。すべて拡張や「$var」、「$@」、「${array[@]}」、「$(command)」などの特殊文字を含めることができるすべての項目。 Bashは「一重引用符」内のすべての内容をリテラルとして扱います。 '、'、`の違いを調べてください。引用符議論次のリンクを確認してください。http://wiki.bash-hackers.org/syntax/words

これはより安全なスクリプトバージョンなので、代わりに使用することをお勧めします。

my_home="/root/mydir"

my_dir="$my_home/var"
dir_work="$my_home/Local"

while IFS= read -r -d '' f; do
    # I'm guessing that you also want to ignore stderr;
    # this is where the 2>&1 came from.
    if lsof -n "$f" | grep '[a-z]' > /dev/null 2>&1; then
        echo "hey, I'm safer now!"
    fi
done < <(find "$dir_work" -type f -print0)


while IFS= read -r -d '' f; do
    echo "2"
done < <(find "$dir_work" -type d -name 'work' -print0)

ご覧のとおり、このIFS変数は空の値に設定されており、read行の先頭と末尾のスペースが切り捨てられないようにします。このreadコマンドは、空の文字列(-d '')を区切り文字として使用し、\ 0に達するまで読み取ります。 findそれに応じて変更する必要があるため、新しい-print0行ではなく\ 0でデータを区切るオプションを使用します。驚くべきことに、悪意のあるファイル名の一部になる可能性があります。これらのファイルを\ nを使用して2つの部分に分割すると、コードが破損します。

あなたはについて読んでみたいかもしれませんプロセスの交換私のスクリプトを完全に理解していない場合。

find ... | while read name; do ...; done出力を読み取るために使用する必要があるという以前の答えfindも悪いかもしれません。上記のループは、while親シェルからコピーされた変数コピーを使用して新しいサブシェルで実行されます。その後、そのコピーを目的の目的に使用できます。ループが終了すると、whileサブシェルのコピーが削除され、親シェルの元の変数は変更されません。

目標がwhileこのループ内のいくつかの変数を変更し、後で親で使用することである場合は、上記のより安全なスクリプトを使用することをお勧めします。これにより、データの損失を防ぐことができます。

おすすめ記事