「file.txt」という名前のすべてのファイルを繰り返し検索し、sedコマンドを実行します。

「file.txt」という名前のすべてのファイルを繰り返し検索し、sedコマンドを実行します。

私のタスクの問題は、そのfile.txtタスクがサブフォルダまたはサブフォルダに配置できることです。一般的な構造は次のとおりです。

   folder
     |___subfolder
             |_____file.txt
     |
     |___subfolder
             |____subfolder
                      |_______file.txt
     etc

前のコードはサブサブフォルダを処理せず、この部分を追加する方法がわかりません(一部のサブフォルダには後続のフォルダがないため)。

 for dir in ./*/ ; do
        if [ -d "$dir" ]; then 
           cd $d;
           for subdir in ./*/; do
               cd $subdir && $(sed command file.txt) && cd ..;
           done
           cd ..
        fi
done

また、次のようなものを使用する一行方法があることも学びましたfind

find . -name 'file.txt' | sed command file.txt

find明らかに、これは私のディレクトリにのみディレクトリを返すので、うまくいきません。file.txt

答え1

努力する:

find . -name 'file.txt' -exec sed command {} +

file.txtこれにより、サブディレクトリでそのファイルという名前のすべてのファイルが検索され、その.ファイルに対して実行されます。sed command

sedそのファイルを変更するには、この-iオプションを追加します。

-exec ... +今は必須ですがPOSIXfind(ヒント:jordanm)、一部の人々はunsupportedを使用している可能性があります+。次のいずれかがある場合は、以下を使用してください(ヒント:unxnut)。

find . -name 'file.txt' -exec sed command {} \;

より安全な選択

ディレクトリ構造をすばやく変更すると、-exec競合状態が発生する可能性があります。セキュリティを強化するには、以下を使用してください-execdir(該当するヒント:unxnut)。

find . -name 'file.txt' -execdir sed command {} +

ディレクトリに現在のディレクトリがある場合、実行はPATH拒否-execdirされます。

答え2

sedコマンドが何をしているのかわからない場合は、sed入力ファイルごとに1つのコマンドを実行しようとします。 、、、、(などのループ(シェルが再帰ワイルドカードをサポートしている場合)を使用してこれを実行
できますが、ループ構文は異なります。forzshksh93yashbashtcshfish

shopt -s globstar        # bash
#set -o globstar         # ksh93
#set -o extended-glob    # yash

for f in **/file.txt; do [ -f "$f" ] && sed 'cmd' "$f"; done

または(他の人が指摘したように)find

find . -type f -name 'file.txt' -exec sed 'cmd' {} \;

今、誰かがこれを「最適化」し、findsを-ism-execと一緒に使用しない理由が気になるでしょう。たとえば、次のようになります。+zsh

sed 'cmd' **/file.txt(.)

もちろん、sedいくつかを呼び出すので、より効率的です。文書オペランドしかしそれ問題である可能性が高いです。簡単にするために、コマンド1を使用して各ファイルの最初の行だけを印刷するとします(ファイル2を内部で編集せずに、結合された出力を
ファイルにリダイレクトまたは確認することもできます)。走るsed1q

find . -name 'file.txt' -exec sed '1q' {} +

または

sed '1q' **/file.txt(.)

しかし、それらのどれも配達できないでしょう。
ファイルオペランドが複数指定されている場合は、指定されたファイルを指定された順序で読み取り、接続を編集する必要があります。
したがって、sed各ファイルの最初の行ではなく、入力の最初の行だけが印刷されます3
今スイッチgnu sedがあります-s

-s, --separate
        consider files as separate rather than as a single continuous long stream

時にはこれが役に立つかもしれませんが、この特別な場合(1q)には役に立ちません。


1q1: 試すのが気に入らない場合は、$d各ファイルの最後の行を削除する必要があります。 2: 時には提案どおりに処理することもできますが、コマンドの 1 つが次のような場合には確かにそうではありません。 3:次の理由によると主張できます。終了 - しかし、次を使用すると同じことが起こります。 2を強調しています。
gnu sed-i-ssedq
qsed -n '1p'q

答え3

ファイルパスにスペース、改行、一重引用符、二重引用符、またはバックスラッシュ文字が含まれていないとします。

find . -name 'file.txt' -type f | xargs sed command

関連情報