別のフォルダにファイルがあります(ファイル拡張子.mvw)。各フォルダに移動して、「D3PLOT_1DForce」文字列(* .mvwファイルにあります)をフォルダ名に置き換えるスクリプトを作成したいと思います。
フォルダ構造は次のとおりです -
- XYZ_DV_L02_P01
- XYZ_DV_L02_P02
- XYZ_DV_L02_P03
私は次のスクリプトを書いた -
#!/bin/sh
for ii in XYZ_DV_L02* ; do
(cd "$ii")
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/"${ii}"/g" "{}" \;
done
動作し、文字列をフォルダ名に変更しますが、すべてのファイルの最初のフォルダ名を変更します。私はsedがforループに入るとは思わない。
sedがループで動作し、ファイル内の文字列をそのフォルダ名に置き換えるにはどうすればよいですか?
答え1
このcd
コマンドはサブシェルで実行されるため、実際には何もしません。したがって、find
コマンドは、.txtの各サブディレクトリ名に対して一度だけ親ディレクトリで実行されますXYZ_DV_L02*
。最初の呼び出しはsed
すべてのファイルの文字列を変更し、その後の呼び出しはsed
文字列を見つけることができませんが、とにかく実行されます。
この試み:
#!/bin/sh
for ii in XYZ_DV_L02* ; do
find "$ii" -iname "*.mvw" -type f -exec sed -i "
s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/${ii}/g" "{}" +
done
編集してくれたStéphane Chazelasに感謝します。
質問のコマンドをコピーしてパスだけfind
を変更しましたが、変更を説明する価値があります。
${ii}
以前は引用されていませんが、今では引数全体を囲む引用の一部ですsed
。+
代わりに、各ファイルに対して1つのコマンドではなく、複数のファイルに対して1つのコマンドが実行され\;
ます。find
sed
編集する
コメントリクエストでは、コレクション内のすべてのシーケンス[-_a-zA-Z0-9]
と拡張子を含むファイル名である代替.h3d
テキストが後に置き換えられます.mvw
。これが私がコメントを理解する方法ですが、うまくいかないようです。パターンのテキストにアクセスするには、を使用できます\1
。特定の要件に合わせてこのキットを調整する必要があるかもしれません。
#!/bin/sh
for ii in XYZ_DV_L02* ; do
find "$ii" -iname "*.mvw" -type f -exec sed -i -r "
s/([-_a-zA-Z0-9]+)\.h3d/${ii}.h3d/g" "{}" +
done
答え2
この試み、
#!/bin/sh
for ii in XYZ_DV_L02* ; do
cd "$ii"
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce/"${ii}"/g" "{}" \;
cd ..
done
forループの最初の入力フォルダにディレクトリを変更し、ファイルを見つけます。ただし、次のループを実行する前に親ディレクトリに戻る必要があります。
答え3
.mvw
ディレクトリ構造に単に変更するファイルを含む複数のサブディレクトリが含まれている場合は、ファイルがfind
どこにあるかを既に知っているため、サブディレクトリを使用する必要はありません。
for pathname in XYZ_DV_L02*/*.mvw; do
sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done
これは、指定されたサブディレクトリ内のすべてのファイルを繰り返し、.mvw
文字列をディレクトリ名に置き換えます。パラメータ拡張は、${pathname%%/*}
文字列の最初の項目以降のすべての項目を削除します。/
$pathname
テスト:
$ tree
.
|-- XYZ_DV_L02_P01
| `-- somefile.mvw
|-- XYZ_DV_L02_P02
| `-- somefile.mvw
`-- XYZ_DV_L02_P03
`-- somefile.mvw
3 directories, 3 files
$ cat XYZ_DV_L02_P0*/*.mvw
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
(ここでループを実行してください)
$ cat XYZ_DV_L02_P0*/*.mvw
Hello XYZ_DV_L02_P01_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P02_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P03_EffPlStrainMax_VonMisesMax!
明らかに深い階層がある場合は、とにかく使用する必要があります。ただし、find
外部ではなく内部でループを実行できます。find
find
find XYZ_DV_L02*/ -type f -name '*.mvw' -exec sh -c '
for pathname do
sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done' sh {} +
.mvw
ここでは、パターンに一致するすべてのディレクトリの下のすべてのファイルを探しますXYZ_DV_L02*/
。見つかったファイルに対して、この回答の先頭にあるループと同じ操作を実行するループを実行します。これにより、任意のディレクトリの下にあるすべてのファイルの文字列がD3PLOT_1DForce
そのディレクトリ名に置き換えられます。.mvw
XYZ_DV_L02*
関連:
この回答は、GNUsed
または他の実装がsed
内部編集にオプション引数を使用しないと仮定しています。-i