
私のタスクの問題は、その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つのコマンドを実行しようとします。 、、、、(などのループ(シェルが再帰ワイルドカードをサポートしている場合)を使用してこれを実行
できますが、ループ構文は異なります。for
zsh
ksh93
yash
bash
tcsh
fish
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' {} \;
今、誰かがこれを「最適化」し、find
sを-ism-exec
と一緒に使用しない理由が気になるでしょう。たとえば、次のようになります。+
zsh
sed 'cmd' **/file.txt(.)
もちろん、sed
いくつかを呼び出すので、より効率的です。文書オペランドしかしそれ問題である可能性が高いです。簡単にするために、コマンド1を使用して各ファイルの最初の行だけを印刷するとします(ファイル2を内部で編集せずに、結合された出力を別
のファイルにリダイレクトまたは確認することもできます)。走るsed
1q
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
)には役に立ちません。
1q
1: 試すのが気に入らない場合は、$d
各ファイルの最後の行を削除する必要があります。 2: 時には提案どおりに処理することもできますが、コマンドの 1 つが次のような場合には確かにそうではありません。 3:次の理由によると主張できます。終了 - しかし、次を使用すると同じことが起こります。 2を強調しています。
gnu sed
-i
-s
sed
q
q
sed -n '1p'
q
答え3
ファイルパスにスペース、改行、一重引用符、二重引用符、またはバックスラッシュ文字が含まれていないとします。
find . -name 'file.txt' -type f | xargs sed command