次のものをすべて見つけて置換するにはどうすればよいですか。
subdomainA.example.com
と
subdomainB.example.com
/home/www/
ディレクトリツリーの下のすべてのテキストファイルに再帰的に?
注 :gitリポジトリを含むフォルダでこのコマンドを実行しないでください。gitを変更すると、gitインデックスが破損する可能性があります。
find /home/www -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'
man find
から:
-print0 (GNU
find
のみ)は、検出されたパス名間の出力区切り文字として空白の代わりにヌル文字(\0
)を使用するようにfind
に指示します。ファイルに空白や他の特殊文字を含めることができる場合、これはより安全なオプションです。-print0
またはfind
を使用する場合は、xargs
に-exec <command>
引数を使用することをお勧めします(xargs
には-0
引数が必要です)。
注 :gitリポジトリを含むフォルダでこのコマンドを実行しないでください。gitを変更すると、gitインデックスが破損する可能性があります。
find /home/www/ -type f -exec \
sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
ここでの他の答えと比較すると、これはほとんどの場合より単純であり、Perlの代わりにsedを使用します。これが元の質問が求めていたものです。
私にとって最も簡単な方法は
grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'
すべてのトリックはほぼ同じですが、私はこれが好きです。
find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} +
find <mydir>
:ディレクトリを調べます。
-type f
:
ファイルの種類:通常のファイル
-exec command {} +
:
この変種の-execは、選択されたファイルに対して指定されたコマンドを実行しますが、コマンドラインは選択された各ファイル名を末尾に追加することによって作成されます。コマンドの総呼び出し数は、一致したファイルの数よりはるかに少なくなります。コマンドラインは、xargsがコマンドラインを構築するのとほぼ同じ方法で構築されています。コマンド内では `{} 'のインスタンスは1つだけ許可されています。コマンドは開始ディレクトリで実行されます。
cd /home/www && find . -type f -print0 |
xargs -0 Perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'
私にとって覚えておくべき最も簡単な解決策は https://stackoverflow.com/a/2113224/565525 です。
sed -i '' -e 's/subdomainA/subdomainB/g' $(find /home/www/ -type f)
_ note _ :-i ''
はOSX問題を解決しますsed: 1: "...": invalid command code .
_ note _ :処理するファイルが多すぎる場合はArgument list too long
が返されます。回避策 - 上記のfind -exec
またはxargs
ソリューションを使用してください。
銀の検索者を使用している人のために (ag
)
ag SearchString -l0 | xargs -0 sed -i 's/SearchString/Replacement/g'
Agはデフォルトでgit/hg/svnファイル/フォルダを無視するので、これはリポジトリ内で実行しても安全です。
再帰的にsed
を通過するようにファイルを削減するには、文字列インスタンスをgrep
にします。
grep -rl <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g
man grep
を実行すると、他の人が丁寧に指摘しているようにgitインデックスの問題を避けて、.gitディレクトリの検索を省略したい場合は--exlude-dir="*.git"
フラグを定義することもできます。
あなたを導く:
grep -rl --exclude-dir="*.git" <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g
エキストラとして1つの素敵なワンライナー。 git grepを使う.
git grep -lz 'subdomainA.example.com' | xargs -0 Perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g"
これはgitリポジトリと互換性があり、少し簡単です。
Linux:
git grep -l 'original_text' | xargs sed -i 's/original_text/new_text/g'
マック:
git grep -l 'original_text' | xargs sed -i '' -e 's/original_text/new_text/g'
find /home/www/ -type f -exec Perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
find /home/www/ -type f
は/ home/www /(およびそのサブディレクトリ)内のすべてのファイルを一覧表示します。 "-exec"フラグは、見つかった各ファイルに対して次のコマンドを実行するようにfindに指示します。
Perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
ファイルに対して実行されるコマンドです(一度に多数)。 {}
はファイル名に置き換えられます。コマンドの最後にある+
は、find
に多くのファイル名に対して1つのコマンドを作成するように伝えます。
find
のmanページによると: "コマンドラインは、xargsがコマンドラインを構築するのとほぼ同じ方法で構築されています。"
したがって、xargs -0
または-print0
を使用せずに、目標を達成する(およびスペースを含むファイル名を処理する)ことが可能です。
私はこれを必要としていただけで、利用可能な例の速度には不満でした。それで、私は自分自身を思いつきました:
cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 Perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'
Ack-grepは関連ファイルを見つけるのに非常に効率的です。このコマンドは〜145 000ファイルを簡単に交換しましたが、他のユーザーはそんなに時間がかかりましたが、完了するまで待ちきれませんでした。
これを試して:
sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *`
あなたは以下のようにこれを解決するためにawkを使うことができます、
for file in `find /home/www -type f`
do
awk '{gsub(/subdomainA.example.com/,"subdomainB.example.com"); print $0;}' $file > ./tempFile && mv ./tempFile $file;
done
これがお役に立てば幸いです。
grep -lr 'subdomainA.example.com' | while read file; do sed -i "s/subdomainA.example.com/subdomainB.example.com/g" "$file"; done
私は、ほとんどの人が何かを「ファイルを読み込んでいる間」にパイプできることを知らないと思いますし、ファイル名の中のスペースを残しながらそれらの厄介な-print0引数を避けます。
Sedの前にecho
を追加すると、実際に実行する前にどのファイルが変更されるのかを確認できます。
#!/usr/local/bin/bash -x
find * /home/www -type f | while read files
do
sedtest=$(sed -n '/^/,/$/p' "${files}" | sed -n '/subdomainA/p')
if [ "${sedtest}" ]
then
sed s'/subdomainA/subdomainB/'g "${files}" > "${files}".tmp
mv "${files}".tmp "${files}"
fi
done
やや古い学校ですが、これはOS Xで動作しました。
いくつかのトリックがあります:
•現在のディレクトリの下にある拡張子.sls
を持つファイルのみを編集します。
•sed
がそれらを「任意の文字」として評価しないようにするため、.
はエスケープする必要があります。
•,
は、通常の/
の代わりにsed
デリミタとして使用されます。
これはvariable
のパスにimport
を渡すようにJinjaテンプレートを編集することにも注意してください(ただし、これはトピック外です)
まず、あなたのsedコマンドがあなたが望むことをしていることを確認してください(これはstdoutへの変更を表示するだけで、ファイルは変更しません):
for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done
変更する準備が整ったら、必要に応じてsedコマンドを編集します。
for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed -i '' 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done
sed コマンドの-i ''
に注意してください。私はオリジナルファイルのバックアップを作成したくありませんでした( OS Xでsedを使ったインプレース編集 またはRobert Lujoのコメント)ページ)。
幸せなsedingの人々!
vim
またはgrep
ツールと一緒にfind
を使用しても構わない場合は、このリンクでユーザーGertの回答をフォローアップできます - > 大きなフォルダ階層でテキスト置換を実行する方法 。
これが契約です:
特定のパスで置き換えたい文字列を再帰的にgrepし、一致するファイルの完全なパスのみを取ります。 (それが$(grep 'string' 'pathname' -Rl)
になります。
(省略可能)これらのファイルを一元管理されたディレクトリに事前バックアップしたい場合は、これを使用することもできます。cp -iv $(grep 'string' 'pathname' -Rl) 'centralized-directory-pathname'
その後、与えられたリンクで提供されているものと同様のスキームに従って、vim
の中で自由に編集/置換することができます:
:bufdo %s#string#replacement#gc | update
これは最も一般的であるべきバージョンです。例えばfind
は必要ありません(代わりにdu
を使用)。それはxargs
を必要とします、それはPlan 9のいくつかのバージョン(9frontのような)だけで見つけられます。
du -a | awk -F' ' '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'
ファイル拡張子のようなフィルタを追加したい場合はgrep
を使用してください。
du -a | grep "\.scala$" | awk -F' ' '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'
によると これ ブログ投稿:
find . -type f | xargs Perl -pi -e 's/oldtext/newtext/g;'
私はちょうどトップスを使います:
find . -name '*.[c|cc|cp|cpp|m|mm|h]' -print0 | xargs -0 tops -verbose replace "verify_noerr(<b args>)" with "__Verify_noErr(<args>)" \
replace "check(<b args>)" with "__Check(<args>)"
また変更を避けるために
それでも
(おそらくドメインルートの背後にある考えでは良くない)
find /home/www/ -type f -exec sed -i 's/\bsubdomainA\.example\.com\b/\1subdomainB.example.com\2/g' {} \;
複数のファイルを変更する(そしてバックアップを*.bak
として保存する)には:
Perl -p -i -e "s/\|/x/g" *
ディレクトリ内のすべてのファイルを取り、|
を「Perlのパイ」と呼ばれるxに置き換えます(パイと同じように簡単です)。
IBMi上のQshell(qsh)の場合、OPでタグ付けされたようにbashしないでください。
Qshコマンドの制限事項
このようにqshの解は:
PATH='your/path/here'
SEARCH=\'subdomainA.example.com\'
REPLACE=\'subdomainB.example.com\'
for file in $( find ${PATH} -P -type f ); do
TEMP_FILE=${file}.${RANDOM}.temp_file
if [ ! -e ${TEMP_FILE} ]; then
touch -C 819 ${TEMP_FILE}
sed -e 's/'$SEARCH'/'$REPLACE'/g' \
< ${file} > ${TEMP_FILE}
mv ${TEMP_FILE} ${file}
fi
done
警告:
Perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *`
Gitリポジトリ内のすべての出現箇所を置き換えるには、次のようにします。
git ls-files -z | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'
参照してください ローカルのgitリポジトリにファイルをリストしますか? リポジトリ内のすべてのファイルを一覧表示するための他のオプション。 -z
オプションは、ファイル名をゼロバイトで区切るようにgitに指示します。これにより、xargs
(オプション-0
を含む)がスペースや何も含まれていなくてもファイル名を区切ることができます。
ディレクトリを除外する (--exclude-dir=.svn
)、および ファイル名にスペースを含める (0Byteとgrep -Z
およびxargs -0
の併用)
grep -rlZ oldtext . --exclude-dir=.svn | xargs -0 sed -i 's/oldtext/newtext/g'
grep
とsed
の組み合わせ
for pp in $(grep -Rl looking_for_string)
do
sed -i 's/looking_for_string/something_other/g' "${pp}"
done
あなたのSVNリポジトリを完全に破壊することなくこれを使いたいのであれば、 'find'に全ての隠しファイルを無視するように指示することができます。
find . \( ! -regex '.*/\..*' \) -type f -print0 | xargs -0 sed -i 's/subdomainA.example.com/subdomainB.example.com/g'
あなたがnodeへのアクセス権を持っているなら、あなたはnpm install -g rexreplace
をすることができます
rexreplace 'subdomainA.example.com' 'subdomainB.example.com' /home/www/**/*.*
これは私がOSXとWindows(msys2)のために私が見つけた最良の万能ソリューションです。 sedのGNUバージョンを取得できるものならどれでも動作するはずです。チェックサムを破壊しないように.gitディレクトリをスキップします。
Macでは、最初にcoreutilsをインストールし、gsedがパスにあることを確認してください -
brew install coreutils
それから私は私のzshrc/bashrcにこの関数を貼り付けます - >
replace-recursive() {
hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed"
find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g"
}
usage: replace-recursive <find> <replace>
現在のディレクトリおよびサブディレクトリ内の .c および .h ファイルのすべての string_1 に一致するすべての string_2 を に置き換えます(.git /を除く) 。
これは Mac で動作します。
find . -type f -path "*.git*" -Prune -o -name '*\.[ch]' -exec \
sed -i '' -e 's/'$1'/'$2'/g' {} +
これは Linux で動作するはずです(まだテストしていません):
find . -type f -path "*.git*" -Prune -o -name '*\.[ch]' -exec \
sed -i 's/string_1/string_2/g' {} +
もっと簡単な方法は、コマンドラインで以下を使用することです。
find /home/www/ -type f|xargs Perl -pi -e 's/subdomainA\.example\.com/subdomainB.example.com/g'