フォルダを繰り返してファイルをインポートし、そのファイルを操作して、ファイルと同じ名前のテキストファイルに出力をリダイレクトしようとしています。 「検索」を使ってみました -
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 {} +
メモ:
for f; do
同じですか?for f in "$@"; do
これ最初コマンドの引数
sh -c '...'
はです。これは、またはによって実行されるsh
プロセステーブルで使用される名前です。sh -c
必要な名前、または-exec
-execdir
$0
sh
find-sh
一般的に使用される名前を使用できます。存在しない場合はシェルスクリプト見えない見つかった最初のファイル名はfind
。これはsh -c
(および他のいくつかのコマンド、通常のようなスクリプトソルバーbash -c
)にのみ当てはまります。いいえ使用または実行したいほとんどのコマンドにfind -exec
必要です-execdir
(つまり、必須ではgrep
ありませんsed
)。これは、ファイルを含むディレクトリを
-type f
探したい場合でも、cd
ディレクトリ(またはソケット、名前付きパイプ、シンボリックリンクなど)ではなく、一般的なファイルのみを扱いたいからです。一般ファイルとシンボリックリンクを処理するには、find-L
オプションまたはを使用します\( -type f -o -type l \)
。-L
ディレクトリへのシンボリックリンクが続きます。外部一般的に望むものではない検索ツリーです。。を使用する場合、埋め込みスクリプトは各引数をチェックして(私の例のように)通常のファイルであるか、一般的なファイルを指すシンボリックリンクであることを確認する必要があります(に記載されている
\( -type f -o -type l \)
ように-hおよび除く)。 -L、すべてのFILE関連テストはシンボリックリンクを逆参照します。sh -c
"$f"
test -f
help test
man 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 {} +
スクリプト内のすべての変数拡張は
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 {} +
-d
findには、またはなどの関連オプションもあり、ディレクトリツリーをナビゲートする方法を制御できます-depth
。-mindepth
cdo
PS:このコマンドが何をするのか、どの引数を使用しているのかわかりませんが、--
オプションの終わりとファイル名引数の先頭を表示するために使用をサポートしている場合は、コマンドに含める必要があります。それ以外の場合は、次-
から始まるファイル名がオプションとして扱われます。たとえば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より優れているのですか?