複数のファイルの内容を一括で置換する
sed
の-i
オプションを使って破壊的な置換を行います。ファイルの対象や構造を完全に理解していない場合は非推奨ですので、自己責任の上で実行してください。
ディレクトリ配下にある、大量のファイルの内容を一括で置換する方法についてのメモです。grep
とsed
の2つのコマンドを使用します。なお、sed
で用いる-i
オプションは、GNUのsed
のオプションです。したがって、macOSといったBSD環境の場合は、別の工夫が必要になります。
本稿では、htmlに記述されている外部CSSのファイル名を変更するケースを取り扱います。具体的には、<link href="~/css/main_0320.css" rel="stylesheet">
を<link href="~/css/main_0401.css" rel="stylesheet">
と、付された数字(月日)を変更します。
ディレクトリ構造は次の通りです。この中のhtmlファイル、~/index.html
、~/blog/index.html
、そして~/blog/2020/n{101..103}.html
が対象です。
$ tree
|--- blog
| |--- 2020
| | |--- n101.html
| | |--- n102.html
| | `--- n103.html
| `--- index.html
|--- css
| |--- main_0320.css
| `--- sub.css
`--- index.html
環境:grep (GNU) 3.4、sed (GNU) 4.8
コマンド例
次のコマンドで、ディレクトリ配下のファイルの内容を一括で置換できます。繰り返しになりますが、対象のファイルを直接操作する破壊的な置換になります。
$ grep -rl 'main.*css' . | xargs sed -i 's/0320/0401/'
grep
で処理対象のファイル名を取得し、xargs
でsed
の引数にgrep
で取得したファイル名を渡していす。
このコマンドが一体何をしているのか、詳しく見ていきましょう。
grepで対象ファイル名を表示する
grep
を使って、置換対象となるファイル名の一覧を取得します。
まず、grep
で置換対象となるcssのリンクが書かれたhtmlファイルを探します。階層型のディレクトリですから、-r
オプションを付けて、再帰的な検索を可能にします。また、-o
オプションを付けて、マッチしたファイル名と文字列のみを表示して結果を見やすくします。最後に任意の検索の開始ディレクトリを指定します。今回は、カレントディレクトリ配下を検索したいので、.
か*
をつけます。
実行すると、マッチした内容が表示されました。これで問題ないか確認します。
$ grep -ro 'main.*css' .
blog/2020/n101.html:main_0320.css
blog/2020/n102.html:main_0320.css
blog/2020/n103.html:main_0320.css
blog/index.html:main_0320.css
index.html:main_0320.css
問題がなければ、-l
オプションを付けてファイル名を表示します。ちなみに、-rol
と書いても同じ結果になります。
$ grep -rl 'main.*css' .
blog/2020/n101.html
blog/2020/n102.html
blog/2020/n103.html
blog/index.html:mai
index.html
sedの引数にgrepの結果を渡す
sed
の引数にgrep
の結果(ファイル名)をxargs
を使って渡します。
$ grep -rl 'main.*css' . | xargs sed 's/main_0320/main_0401/'
実行すると、置換されたファイルの内容が表示されます。内容を確認して問題がなければ、sed
に-i
オプションを付けで実行すると置換されます。
$ grep -rl 'main.*css' . | xargs sed -i 's/main_0320/main_0401/'
更新情報
- 作成日:2020-03-23
- 更新日:2022-04-28