MacとLinuxのテキストファイルでの再帰的な検索と置換


127

Linuxシェルでは、次のコマンドは再帰的に「this」のすべてのインスタンスを検索し、「that」で置き換えます(目の前にLinuxシェルはありませんが、実行する必要があります)。

find . -name "*.txt" -print | xargs sed -i 's/this/that/g'

OSXでの同様のコマンドはどのようになりますか?


apple.stackexchange.comLinuxやすべての開発者にとって一般的ではないため、おそらくに移動する必要があります。
AlikElzin-kilaka 16

回答:


246

OS XはBSDツールとGNUツールを組み合わせて使用​​しているため、常にドキュメントを確認することをお勧めします(ただしless、OS Xのマンページに準拠していないドキュメントも確認しました)。

https://web.archive.org/web/20170808213955/https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html

sedは、-iバックアップの拡張子としてafterの引数を取ります。-i ''バックアップしない場合は、空の文字列()を指定します。

次のことを行う必要があります。

LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +

これ-type fは良い習慣です。ディレクトリを指定すると、sedは文句を言うでしょう。 -execよりも優先されxargsます。-print0何も気にする必要はありません。{} +最後の手段でfindはなく、と呼ばれるコマンドの1つのインスタンスに引数としてすべての結果を追加する各結果のためにそれを再実行しています。(1つの例外は、OSで許可されているコマンドライン引数の最大数に違反している場合です。その場合find、複数のインスタンスが実行されます。)


2
この置換の「this」にはスラッシュ(localhost / site)が含まれています-.htmlファイルのURLの一部を置換しています。二重引用符を入れてみましたが失敗しました。
ティモシーT.

6
Sed構文では、スラッシュの代わりにほとんどすべての文字を使用できます。たとえば、次の%文字を使用できますsed "s%localhost/site%blah/blah%"。もう1つの方法は、セパレーターをバックスラッシュでエスケープすることですsed "s/localhost\/site/blah\/blah/"
TaylanUB 2013

試していただきありがとうございます。ただし、スラッシュを区切るために{}を使用してみましたが、それでもエラーが発生しました...
Timothy T.

16
他に誰かがillegal byte sequenceエラーを出している?もしそうなら、試してください:LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +それは私のために働いた。
ColdTuna 2016年

10
これは、ファイルごとに1つだけ使ってくださいocurrenyを交換する/gように複数のocurrenciesためLC_ALL=C find . -type f -exec sed -i '' s/search/replace/g {} +
jamesjara

152

Macの場合、より類似したアプローチは次のようになります。

find . -name '*.txt' -print0 | xargs -0 sed -i "" "s/form/forms/g"

10
私がそれに戻ってそれを使用するたびに、これに賛成票を投じることができればいいのにと思います。たった今+15でしょう、簡単です。
Droogans 2015

どういうわけか、私にはうまくいきません。何もしません。-私は、次のコマンドを実行している、私はフォルダform360内だと-私はform360に名前easyformですべての文字列のインスタンスを変更しようとしている:find . -name '*.php' -print0 | xargs -0 sed -i "" "s/easyform/form360/g"
アンドレス・ラモス

2
私にとっては、これは正解です。それは私のために働いた唯一のものです。
nosequeldeebee 2017

1
-print0 | ファイル名にスペースが含まれていると、xargs -0がMacで機能しません。
user2807219

1
sed:。:インプレース編集は通常のファイルに対してのみ機能します
codeslapper

14

代替ソリューションとして、Mac OSX 10.7.5でこれを使用しています

grep -ilr 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

クレジットは次のとおりです:Todd Cesereの回答


これはうまくいきます!他のスクリプトは、OSXの場合によっては行末を追加します。どうもありがとう!
Sebastien Filion

14

Mac OSX 10.11.5では、これは正常に機能します。

grep -rli 'old-word' * | xargs -I@ sed -i '' 's/old-word/new-word/g' @

xargs -I @ sed -i '' 's / old-word / new-word / g' @は、他の多くの機能しない提案を試した後、私にとってはうまくいきました。ありがとうございました!
DrB 2016

13

上記のどれもOSXでは動作しません。

以下をせよ:

perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt

1
SEARCH_FORとREPLACE_WITHがパスの場合、「/」をエスケープする方法
rraallvv 2013年

別の区切り文字を使用してください。パスを使用している場合は、コロンまたはパイプが機能します。's | SEARCH | REPLACE | g'など。「s {SEARCH} {REPLACE}」のように、中括弧を使用します。
dannysauer 2013

1
ditoの質問です。Macで試してみませんか-エラーが発生するようですが?たとえば、私のパスはファイルとして解釈されますか?-bash:localhost / nohost:そのようなファイルやディレクトリはありません
ティモシーT.

これは深いフォルダを再帰しません。1レベルのみ。
セルゲイロマノフ

このコマンドの詳細については、こちらをご覧ください。lifehacker.com
5810026 /

7

LinuxとMac OS Xの両方で動作するバージョン(に-eスイッチを追加することによりsed):

export LC_CTYPE=C LANG=C
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/this/that/g'

私はこの回答+承認された回答の行をエクスポートする必要がありました(バックアップファイルを生成したくありませんでした)
Lance

2
アドレス「不正なバイトシーケンス」エラーに、コマンドを実行する前に、ロケールを設定してみてください: export LC_CTYPE=C && export LANG=C
cjoy

Gitを使用している場合は、「*。filetype」ではなく「*」を使用してこれを実行しないでください。または、未公開のすべての作品に別れを告げることもできます。
セルゲイ

1
Macバージョンのsedコマンドでは-iの後に ''が必要なので、この答えは正しくありません
G Huxley

2

私がこのコマンドを入力するときはいつでも、私はいつもそれをホースアップするか、フラグを忘れているようです。現在のディレクトリからグローバル検索置換を行うTaylanUBの回答に基づいてgithubにGistを作成しました。これはMac OSX固有です。

https://gist.github.com/nateflink/9056302

ターミナルをポップオープンしてコピーするだけでいいのです。

curl -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

奇妙なバイトシーケンスエラーが発生する可能性があるため、以下に完全なコードを示します。

#!/bin/bash
#By Nate Flink

#Invoke on the terminal like this
#curl -s https://gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: ./$0 [find string] [replace string]"
  exit 1
fi

FIND=$1
REPLACE=$2

#needed for byte sequence error in ascii to utf conversion on OSX
export LC_CTYPE=C;
export LANG=C;

#sed -i "" is needed by the osx version of sed (instead of sed -i)
find . -type f -exec sed -i "" "s|${FIND}|${REPLACE}|g" {} +
exit 0

2

これは私の実行可能なものです。Mac OS X 10.10.4の場合

grep -e 'this' -rl . | xargs sed -i '' 's/this/that/g'

上記のようにfindを使用すると、検索テキストを含まないファイルが変更されます(ファイルの最後に新しい行を追加します)。これは冗長です。


2

zsh端末を使用している場合は、ワイルドカードマジックを使用できます。

sed -i "" "s/search/high-replace/g" *.txt


1

私はこの形式を使用しましたが、...非常に奇妙なすべてのインスタンスを実際に変更するには、3回以上実行する必要があることがわかりました。一度実行すると、すべてではなく各ファイルの一部が変更されます。まったく同じ文字列を2〜4回実行すると、すべてのインスタンスがキャッチされます。

find . -type f -name '*.txt' -exec sed -i '' s/thistext/newtext/ {} +

あなたはこのコマンドを複数回実行する必要がありましたb / cあなたのsed正規表現gは最後にa を必要とします、そうでなければそれは行の最初の出現のみを置き換えthistextます。したがって、正規表現は次のようになりますs/thistext/newtext/g
Les Nightingill

0

https://bitbucket.org/masonicboom/serpは、OSXでテストされたgoユーティリティ(つまり、クロスプラットフォーム)であり、特定のディレクトリ内のファイル内のテキストを再帰的に検索および置換し、各置換を確認します。それは新しいので、バグがあるかもしれません。

使用法は次のようになります。

$ ls test
a  d  d2 z
$ cat test/z
hi
$ ./serp --root test --search hi --replace bye --pattern "*"                         
test/z: replace hi with bye? (y/[n]) y
$ cat test/z
bye


-3

OSXでのコマンドは、きれいなUIでのUnixとまったく同じである必要があります。


私は同じくらい考えましたが、いや。sedにフィードするとき、ファイルの前に./が置かれるため、sedは「無効なコマンドコード」を報告します。多分私はただ疲れています;-)
Jack

@ JacobusR、OSX端末からカットアンドペーストしてください-少し違うものを入力する必要があります。
グレン・ジャックマン2012年

3
あなたは望むこと-print0に追加findフラグと-0するxargsフラグ。
jmtd 2012年

and xargsの-exec sed -i s/this/that/g {} \+代わりに使用することもできます-print
Marian

@JacobusR-先頭の「./」パス名があってもこれは機能します。ただし、ファイル名にスペースがある場合、「./ jacobus \ R.txt」のように使用するとxargs、スペースで区切られた「./jacobus」がに渡されるファイルとして表示されsed、「R.txt」 、どちらも存在しません。
ブレットヘイル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.