10.

Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順

編集
この記事の要点
  • 定番は find ディレクトリ -type f -print0 | xargs -0 sed -i "s/置換前/置換後/g"
  • sed -iファイルを直接書き換えるので、必ず 事前バックアップ-i.bak 拡張子付きで実行
  • バイナリ巻き込み防止には grep -lr で対象ファイルを絞ってから渡すのが安全
  • 対象拡張子を絞るときは find ... -name "*.txt"、除外は -not -path
  • 本番では絶対パス指定 + ログ保存 + バックアップを徹底

やりたいこと

あるフォルダ以下の複数ファイルにまたがる文字列を、一括で置換したいというニーズです。設定ファイル一斉更新、リネーム反映、URL の変更などで頻出します。Linux/macOS では find + sed の組み合わせが定番です。

定番の書き方

find /path/to/dir -type f -print0 | xargs -0 sed -i "s/置換前文字列/置換後文字列/g"
部品役割
find /path/to/dir -type f指定ディレクトリ以下のファイルを列挙
-print0NUL 区切りで出力(スペース・改行入りのファイル名対策)
xargs -0NUL 区切りで読み取り、sed の引数に展開
sed -i "s/A/B/g"ファイル内の A をすべて B に置換し、ファイルを直接書き換える

使用例

# /etc/myapp 以下の "Windows" を "Linux" に一括置換
find /etc/myapp -type f -print0 | xargs -0 sed -i "s/Windows/Linux/g"

# 拡張子で絞る
find ./src -type f -name "*.php" -print0 | xargs -0 sed -i "s/old_func/new_func/g"

必ず dry-run(プレビュー)してから実行

# 1. どのファイルに含まれているか確認
grep -rl "置換前文字列" /path/to/dir

# 2. 実際にどう変わるかプレビュー(sed -i ではなく出力に流す)
grep -rl "置換前文字列" /path/to/dir | xargs sed -n 's/置換前文字列/置換後文字列/gp'

# 3. 問題なければ本番実行
grep -rlZ "置換前文字列" /path/to/dir | xargs -0 sed -i "s/置換前文字列/置換後文字列/g"

本番置換の前に必ず対象ファイルと差分の確認を行うのが鉄則。grep -lr でテキストファイルだけに絞ると、画像 / アーカイブなどバイナリへの誤適用を防げます。

バックアップ付きで安全に

# -i.bak を付けると、元ファイルを .bak に残してから書き換える
find /path/to/dir -type f -name "*.conf" -print0 \
  | xargs -0 sed -i.bak "s/old.example.com/new.example.com/g"

# 上手くいったら .bak を一括削除
find /path/to/dir -type f -name "*.bak" -delete

macOS の BSD sed は-i の後に拡張子が必須sed -i '' "s/.../.../g" のように空文字列でも明示)。Linux と macOS 両対応スクリプトでは -i.bak 形式が無難です。

区切り文字を変える(パスを含む置換)

置換対象に /(スラッシュ)が多く含まれるときは、sed の区切り文字を |# に変えると読みやすくなります。

# パスの置換でスラッシュをエスケープしなくて済む
find . -type f -name "*.conf" -print0 \
  | xargs -0 sed -i "s|/var/log/old|/var/log/new|g"

正規表現とエスケープ

# 拡張正規表現を使う
find . -type f -name "*.txt" -print0 \
  | xargs -0 sed -i -E "s/[0-9]{4}-[0-9]{2}-[0-9]{2}/YYYY-MM-DD/g"

# キャプチャを使った置換
find . -type f -name "*.html" -print0 \
  | xargs -0 sed -i -E 's|href="/old/([^"]+)"|href="/new/\1"|g'

特定ディレクトリを除外

# node_modules / .git は除外
find . \
  \( -name node_modules -o -name .git -o -name vendor \) -prune \
  -o -type f -print0 \
  | xargs -0 sed -i "s/古い社名/新しい社名/g"

perl で複数行・複雑な置換

複雑な正規表現や非貪欲マッチが必要なときは perl -i -pe が便利です。

find . -type f -name "*.md" -print0 \
  | xargs -0 perl -i -pe 's/\bfoo\b/bar/g'

# 複数行マッチ
find . -type f -name "*.html" -print0 \
  | xargs -0 perl -i -0pe 's|<script[^>]*>.*?</script>||gs'

VS Code / IDE での代替

「Ctrl + Shift + H」でプロジェクト全体の検索と置換ができます。差分プレビュー付き・選択置換も可能で、誤適用のリスクが低く便利です。スクリプト化が必要なケース以外は GUI が早いことも多い。

本番運用のチェックリスト

  • パスは絶対パスで書く
  • 必ず grep -rl対象ファイル数を確認
  • 差分は sed -n 'p'diff事前プレビュー
  • 本番直前にディレクトリごと tar でバックアップ
  • 失敗時の復旧コマンドを準備(バックアップから戻す)
  • Git 管理下なら事前コミット&ブランチ作成で差分検証

関連

  • Linux — 親カテゴリ
  • find / xargs / grep / sed / awk — テキスト処理コマンド
  • perl -i -pe — 複雑な置換
  • diff / patch — 差分の確認と適用
  • VS Code / IDE の検索置換 — GUI での代替
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. ディストリビューション
  2. コマンド一覧
  3. Linuxのサーバーに登録されているユーザの一覧を確認するコマンド
  4. リポジトリの一覧の確認
  5. エラー一覧
  6. ショートカットキー一覧
  7. ログを確認する便利なコマンド
  8. cronの導入と実行方法 (CentOS 7編)
  9. ディレクトリ内のファイル数を確認
  10. 複数ファイル内の文字列を一括置換する方法

最近更新/作成されたページ