近頃のIDEや高級エディタでは、プロジェクトの全ファイルから文字列を検索して一括置換できるものが多いのですが、残念ながら一括置換が無かったり、IDEを起動するのが面倒だったり、そもそもIDEを使えないこともあります。
そこで、CLIで全ファイル一括置換する方法をご紹介します。
git ls-files を使えばよい
レポジトリ内の全ファイルをリストアップできます。
$ git ls-files --help
NAME
git-ls-files - Show information about files in the index and the working tree
SYNOPSIS
git ls-files [-z] [-t] [-v]
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])*
(-[c|d|o|i|s|u|k|m])*
[--eol]
[-x <pattern>|--exclude=<pattern>]
[-X <file>|--exclude-from=<file>]
[--exclude-per-directory=<file>]
[--exclude-standard]
[--error-unmatch] [--with-tree=<tree-ish>]
[--full-name] [--recurse-submodules]
[--abbrev] [--] [<file>...]
(以下略)
なので、sed
コマンドなどの編集コマンドとつなげば一括置換は簡単です。
$ git ls-files | xargs -L 1 sed -e 's/before_filter/before_action/g' -i
$ git ls-files | while read -r f; do sed -e 's/before_filter/before_action/g' -i "$f"; done
コマンドにしてみた(git-sed)
毎回パイプやwhile
を書くのが面倒なので、コマンドにしてみました。
git sed 's/before_filter/before_action/g'
で使えます。
#!/bin/bash
set -euC
if [ "$#" -eq 0 ]; then
echo 'git sed [SED-COMMANDS]' >&2
exit 1
fi
if which gsed > /dev/null; then
SED=gsed
else
SED=sed
fi
cmd=()
while [ "$#" != "0" ]; do
cmd+=(-e "$1")
shift
done
git ls-files | while read -r f; do
# シンボリックリンクにはsedを適用しない(リンクを一度削除して、通常のファイルとして作り直してしまうため)
[ -f "$f" ] && [ ! -L "$f" ] && "$SED" -i "${cmd[@]}" "$f"
done