page_path\example_filename.txt
文字列内のバックスラッシュをスラッシュに置き換えたいです。また、これを大規模なファイル システムで実行し、すべてのディレクトリを再帰的に検索できるようにしたいと考えています。
ウェブ上で、、、を使用するように言っている人を見つけましたgrep
がxargs
、sed
うまくいきませんでした。区切り文字やエスケープ文字のさまざまなバリエーションを試しましたが、うまくいきませんでした。
実行しようとしたコマンドは次のとおりです。
grep -lr -e 'page_path\\' * | xargs sed -i 's/page_path\/page_path//g'
前もって感謝します。
答え1
を使用するとgrep | xargs
、ファイル名内の空白、引用符、バックスラッシュ (実装によってはその他もろもろxargs
) で問題が発生します。
grep
およびの GNU 実装では、区切り文字としてゼロバイトを使用する をxargs
使用することでこれらの問題を回避できます。grep -lZr ... | xargs -r0 sed ...
さて、sed コマンドについてですが、コツは、s/a/b/
区切り文字として他の文字の代わりに使用できることです。例s#a#b#
:
sed -i 's#page_path\\#page_path/#g'
答え2
また、そのためには find を使うこともできます:
find /your/path -type f -exec grep -l 'page_path\\' {} \; -exec sed -i 's#page_path\\#page_path/#g' {} \;
2 番目の exec は最初の exec が成功した場合にのみ実行され、ファイル名に印刷できない文字やエスケープが必要な文字に関する問題は発生しません。
答え3
なぜCPUサイクルを無駄にして、それらのコマンドをすべて呼び出すのでしょうか?バッシュはるかに少ない入力で実行できる機能が組み込まれていますか?
例
str='page_path\example_filename.txt'
echo "${str//\\/\/}"
出力
page_path/example_filename.txt
答え4
ripgrep
ここでも役立ちます。foo を一致させたいものに置き換え、rg
呼び出しとsed
式の両方を変更します。
rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'
ファイル名に空白文字が含まれている可能性がある場合は、ripgrepにNULLバイトで区切るように指示します。
rg foo --files-with-matches -0 | xargs -0 sed -i 's/foo/bar/g'
ソース:https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#検索と置換