フロー制御でglobを使用するには?

フロー制御でglobを使用するには?

ディレクトリリスト(必要に応じてフォルダリスト)があります。

<something>.txt各ディレクトリには、データベースダンプから生成されたというファイルがあります。

ファイルが見つからない場合は、コマンドが失敗し、尊重してディレクトリに移動し、残りのチェックを完了できないため、ファイルが存在する場合にのみ進んで名前を変更する<something>.txtcronジョブを実行したいと思います。 "${PWD##*/}"_info.txt*.txtmvcd ..どちらが意図的ですか?いいえ以下のコードスニペットで説明または表示されています。

したがって、CONTEXTコードは次のようになります。

fの場合<ディレクトリ一覧>
する
  CD "${f}"
  if [-e "*.txt"];       ←質問部分です
    mv *.txt "${PWD##*/}".txt ← 残りはコンテキストを提供するだけです。
  フィリピン諸島
  CD..
完璧

この小さなクリップについての専門家のコメントがありますか?

この例をまとめました。重要な部分は条件です:

[ -e "*.txt" ]

ファイルが存在しても<something>.txt条件は失敗します。

それが私が尋ねるものです。

答え1

1つの可能性は、globでこれらの項目で配列を作成し、配列に要素があるかどうかを確認できることです。たとえば、

cur_opt=$(shopt -p nullglob) # get current status so we can restore
shopt -s nullglob # to let the glob expand to nothing
txt_files=( *txt )
$cur_opt # restore nullglob setting to what it was before
if [ ${#txt_files} -gt 0 ]; then
    ...
fi

ファイルに対して操作を実行するには、配列に要素があるかどうかをテストするのではなく、配列を繰り返すこともできます。

一致するものがあるかどうか本当に確認したい場合は、compgen次のようなものを使用できます。

if [ ! -z "$(compgen -G "*.txt") ]; then
    ...
fi

これは単にリターンを確認することができるcompgenので、

if compgen -G "*.txt" &>/dev/null; then
    ...
fi

答え2

この小さなビデオについて、専門家は次のように言います。

  1. ディレクトリリストと複数のファイル(プリンシパル名が不明)を処理する場合は、fディレクトリ名を表すために使用しないでください。本当に混乱しています。
  2. 単に変更せずに(例えば、##または%)シェル変数自体を(他のものに関連付けずに)処理する場合、中括弧は必要ありません:/バラより問題を回避するには、いつ変数の周りに二重引用符を追加する必要がありますか"${var}"

    したがって、私は外側のループが次のようになることを提案します。

    dのため<ディレクトリ一覧>
    する
        CD "$d"
        (各ディレクトリで実行されるコード)
        CD..
    完璧

@Eric Renoufの完璧な答えに加えて、書く方法はいくつかあります。(各ディレクトリで実行されるコード)。以下は、試したものと同様の簡単なものです。

for f in *.txt
do
    if [ -e "$f" ]
    then
        mv -- "$f" "${PWD##*/}".txt
    fi
done

<something>.txtディレクトリにファイルが1つしかない場合は、必要に応じて機能します。for f …ループは$fファイル名と同じ名前で一度実行され、ファイル名が変更されます。 (私はmv --名前が次に終わるのを防ぐために使用します。- それ以外の場合はオプションとして解釈されます。現在のディレクトリのファイルであるか、相対パス名mv ./"$f" …が確実である場合は安全かもしれません。 )ディレクトリにファイルが$fない場合、ループも一度実行され(文字通り)と同じ効果が表示されます。その名前のファイルがないため、テストは失敗し、実行されません。*.txt$f*.txt-emv

ディレクトリに複数のテキストファイルがある場合、問題が発生する可能性があります。もしあればNこのようにファイルを保存すると、ループが実行されます。N"${PWD##*/}".txt各テキストファイルの名前は.asに変更されます。ジャカリーブラディは次のように指摘しています。、これにより、最後のファイルが最初のファイルを上書きする可能性があります。N-1つのファイル。この問題を解決する1つの方法は、既存のファイルを上書きしようとしたときに警告を表示し、承認または拒否オプションが提供されるようにコマンドに-iオプションを追加することです。mvもちろん、cronスクリプトがジョブとして実行されている場合は役に立ちません。別の方法は、breakループにコマンドを追加することです。

*.txtのfについて
する
    if [-e "$f"]
    それから
        mv - "$f" "${PWD##*/}".txt
        残り
    フィリピン諸島
完璧

これにより、ループが一度だけ実行されます。ループが実行されると、breakループを終了するコマンドが実行されるためです。これにより、最初のテキストファイルのみが名前変更され、他のファイルは保持されます。ファイルが複数あるという通知は受け付けません。

やや複雑なアプローチは、複数ファイルの状況を検出して処理することです。

最初 = 1
*.txtのfについて
する
    if [-e "$f"]
    それから
        if["$first"]
        それから
            mv - "$f" "${PWD##*/}".txt
            最初の=
        その他
            printf "警告: %s ファイルの名前が変更されませんでした。\n" "$f"
        フィリピン諸島
    フィリピン諸島
完璧

ここで、firstフラグはループの先頭にセットされ、最初の反復中にクリアされるので、後続の反復では最初のものではないことがわかります。あるいは、"${PWD##*/}".txtすでに存在していることを確認することもできます。

関連情報