ファイルをインポートし、そのファイルに対していくつかの操作を実行するためにサブディレクトリを繰り返します。

ファイルをインポートし、そのファイルに対していくつかの操作を実行するためにサブディレクトリを繰り返します。

フォルダを繰り返してファイルをインポートし、そのファイルを操作して、ファイルと同じ名前のテキストファイルに出力をリダイレクトしようとしています。 「検索」を使ってみました -

cd /filepath/orig/v1

for dir in $(find . -type d); do
  cd $dir
  for subdir in $(find . -type d); do
          cd $subdir
          for file in `ls`; do
                  echo $file
                  touch $file.txt
                  cdo info $file > $file.txt
          done
  done
done

しかし、これはうまくいきません。ディレクトリ構造は - /filepath/orig/v1/level1/level2/file.nc と似ていますが、サブディレクトリは 2 つ以上のレベルを持つことができます。

答え1

これにはループは必要ありません。検索はすべてを行います。

find . -type f ! -name '*.txt' -print -exec sh -c 'cdo info {} > {}.txt' \;

これにより、既存の.txtファイルが破損するため、「* .txtではない」よりも具体的なファイル名フィルタを使用する必要があります。

答え2

2段階の固定ディレクトリ構造がある場合:

shopt -s dotglob nullglob

for pathname in /filepath/orig/v1/*/*; do
    [[ $pathname == *.txt ]] && continue

    printf 'Processing "%s"\n' "$pathname" >&2
    
    cdo info "$pathname" >"$pathname.txt"
done

まず、シェルオプションを有効にdotglobしますnullglob。これらのシェルオプションを使用すると、ワイルドカードパターンが隠された名前(dotglob)と一致し、パターンが一致することを確認できます。いいえ一致は完全に削除されます(;これは、一致する名前がないとnullglobループが単一の反復を実行しないことを意味します)。/filepath/orig/v1/*/*

ループですでに終わっているすべての名前は.txtスキップされ、残りはファイルを生成するcdo infoために処理されます(これが実際に何をしているのか.txtわかりません)。ファイル名を最初に入力するcdo info必要はありません。そのファイルにリダイレクトすると、ファイルが生成されるためです。touch

関連:


ご存知の場合は、次の名前で終わるファイルのみを処理します.nc

shopt -s dotglob nullglob

for pathname in /filepath/orig/v1/*/*.nc; do
    printf 'Processing "%s"\n' "$pathname" >&2
    cdo info "$pathname" >"$pathname.txt"
done

名前が終わるすべてのファイルを処理したい場合.nc どこかに以下/filepath/orig/v1

find /filepath/orig/v1 -type f -name '*.nc' -exec sh -c '
    for pathname do
        printf "Processing \"%s\"\n" "$pathname" >&2
        cdo info "$pathname" >"$pathname.txt"
    done' sh {} +

これにより、終わる見つかった名前がバッチ処理されます.nc

サブディレクトリのみを検索し、独自のディレクトリを検索しない/filepath/orig/v1/*/検索パスとして使用することもできます。find/filepath/orig/v1/filepath/orig/v1

答え3

概念を理解するのが難しくて「探す」をあきらめたが、これが効果があると思います〜

orig_dir='/filepath/orig/v1'

for entry in "$orig_dir"/*/*; do
    cd "$entry"
    x=`ls *.nc`
    echo "$x"
    name=`basename $x .nc`
    cdo info "$x" > new_path/"$name".txt
    
done

答え4

このオプションは、GNUまたはBSDを使用している場合にfind使用できます。最初にファイルが含まれているディレクトリに変更されることを除いて、他のものと同じです-execdir(終了の代わりに-execdirを使用すると、ディレクトリごとの分岐量を最小限に抑えるために同じディレクトリにファイルをバッチ処理します)。例えば-exec+;

find . -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info "$f" > "$f.txt"; done' sh {} +

メモ:

  1. for f; do同じですか?for f in "$@"; do

  2. これ最初コマンドの引数sh -c '...'はです。これは、またはによって実行されるshプロセステーブルで使用される名前です。sh -c必要な名前、または-exec-execdir$0shfind-sh一般的に使用される名前を使用できます。存在しない場合はシェルスクリプト見えない見つかった最初のファイル名はfind。これはsh -c(および他のいくつかのコマンド、通常のようなスクリプトソルバーbash -c)にのみ当てはまります。いいえ使用または実行したいほとんどのコマンドにfind -exec必要です-execdir(つまり、必須ではgrepありませんsed)。

  3. これは、ファイルを含むディレクトリを-type f探したい場合でも、cdディレクトリ(またはソケット、名前付きパイプ、シンボリックリンクなど)ではなく、一般的なファイルのみを扱いたいからです。一般ファイルとシンボリックリンクを処理するには、find-Lオプションまたはを使用します\( -type f -o -type l \)-Lディレクトリへのシンボリックリンクが続きます。外部一般的に望むものではない検索ツリーです。

    。を使用する場合、埋め込みスクリプトは各引数をチェックして(私の例のように)通常のファイルであるか、一般的なファイルを指すシンボリックリンクであることを確認する必要があります(に記載されている\( -type f -o -type l \)ように-hおよび除く)。 -L、すべてのFILE関連テストはシンボリックリンクを逆参照します。sh -c"$f"test -fhelp testman test

    find . \( -type f -o -type l \) -execdir \
      sh -c 'for f; do
               printf "%s\n" "$f"
               [ -f "$f" ] && cdo info "$f" > "$f.txt"
             done' sh {} +
    
  4. スクリプト内のすべての変数拡張はsh -c二重引用符で囲まれています。そうしなければならないように(参照スペースやその他の特殊文字が原因でシェルスクリプトが停止するのはなぜですか?なぜ)


検索の深さを制限する必要がある場合は、この-maxdepthオプションを使用できます。例えば

find . -maxdepth 2 -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info "$f" > "$f.txt"; done' sh {} +

-dfindには、またはなどの関連オプションもあり、ディレクトリツリーをナビゲートする方法を制御できます-depth-mindepth


cdoPS:このコマンドが何をするのか、どの引数を使用しているのかわかりませんが、--オプションの終わりとファイル名引数の先頭を表示するために使用をサポートしている場合は、コマンドに含める必要があります。それ以外の場合は、次-から始まるファイル名がオプションとして扱われます。たとえばcdo

find . -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info -- "$f" > "$f.txt"; done' sh {} +

printfこれが私が代わりに使用する理由の一部ですecho。バラよりなぜprintfがechoより優れているのですか?

関連情報