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. 複数ファイル内の文字列を一括置換する方法