GUIがあれば完璧だった。コマンドは難しくて覚えられず罠がたくさんある。
追記
2017-09-17。すぐ見てコピペできる正確なコマンドが欲しくて。追記以外のコマンドはエラーが出たのがあったので無視すべし。
grep置換。MinPitchClass
をMin
に置換。
find . -type f -name "*.py" -print0 | xargs -0 sed -i.bak 's/MinPitchClass/Min/g' find . -type f -name "*.py" -print0 | xargs -0 sed -i.bak 's/MaxPitchClass/Max/g' find . -type f -name "*.bak" -print0 | xargs -0 rm -f
grep検索。database.src.Data
を含むファイルを探す。
$ find . -name "*.py" -print0 | xargs -0 grep 'database.src.Data'
カレントディレクトリ配下以下すべての*.py
ファイルを対象とする。(ディレクトリを再帰的に検索するので子、孫、などのディレクトリ配下にあるファイルも対象)
置換前 | 置換後 |
---|---|
MinPitchClass | Min |
MaxPitchClass | Max |
主に使うコマンドは以下。
コマンド | 概要 |
---|---|
find |
ファイルやディレクトリを見つけてechoする |
xargs |
echoを他のコマンドに渡す |
sed |
ファイルの任意テキスト部分をgrep置換する |
findコマンドの引数。
引数 | 説明 |
---|---|
-type f |
ファイルが対象。ディレクトリ等は対象外。誤爆防止。ディレクトリ=d , シンボリックリンク=l 参考 |
-name "*.py" |
末尾.py のファイル名が対象。誤爆防止。 |
-print0 |
xargs コマンドの-0 とセットで使う。ファイルパスに半角スペースがあってもOKにする。 |
xargsコマンドの引数。
引数 | 説明 |
---|---|
-0 |
find コマンドの-print0 とセットで使う。ファイルパスに半角スペースがあってもOKにする。 |
sedコマンドの引数。
引数 | 説明 |
---|---|
-i.bak |
.bak ファイル作成 |
's/MinPitchClass/Min/g' |
's/このテキストを/このテキストに置換する/g' |
- findとxargsコマンドで-print0オプションを使う理由(改) - Qiita
- http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230879/
- http://www.linux-cmd.com/find.html
参考
複数のファイル内の文字列をまとめて置換するLinuxコマンド - Qiita
http://bitwalker.dtiblog.com/blog-entry-185.html
http://saba.omnioo.com/note/1015/find%E3%81%A8%E3%81%8Bgrep%E3%81%A8%E3%81%8B%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E5%86%8D%E5%B8%B0%E7%9A%84%E6%A4%9C%E7%B4%A2%E3%81%AA%E3%81%A9/
コマンド
find . -type f | xargs sed -i 's/置換対象文字列/置換後文字列/g'
-i.bak
で拡張子.bak
のバックアップファイルを残す。
find . -type f | xargs sed -i.bak 's/置換対象文字列/置換後文字列/g'
今回はself.data.acc
をself.data.account
に一括置換したい。
find . -type f | xargs sed -i.bak 's/self.data.acc/self.data.account/g'
拡張子.py
のファイルに限定する。
find . -name '*.py' | xargs sed -i.bak 's/self.data.db_acc[/self.data.db_account[/g'
find . -name '*.py' | xargs sed -i.bak 's/self.data.db_acc./self.data.db_account./g'
find . -name '*.py' | xargs sed -i.bak 's/self.data.db_acc =/self.data.db_account =/g'
メタ文字
sed
コマンドのメタ文字は\n
(nは数字), &
。\
を表したいなら\\
, /
を表したいなら\/
, &
を表したいなら\&
と思われる。たぶん。
問題
対象ファイルが1件もなかった。かわりに*.py
ファイルすべてに*.py.bak
ファイルが生成されてしまった。diffをとっても差分なし。ただのゴミファイル。
差分があるときだけ.bak
ファイルを作ってくれることを期待していたが、そうではないらしい。
ファイル一括削除
そこで、以下のようにして一括削除した。
find . -type f -name '*.bak' | xargs rm
以下のようにしてもカレントディレクトリ直下のみ削除だった。ディレクトリ配下の該当ファイルすべての削除はしてくれなかった。
rm -r -name *.bak
ディレクトリ一括削除
複数のリポジトリを結合したため、個別に.git
ディレクトリがいくつか残っていた。
$ find . -type d -name .git ./uploader/.git ./database/src/repo/create/.git
ファイル一括削除とは微妙に異なるrm
パラメータ。-d
はディレクトリが空でないと削除できないという謎仕様。
$ find . -type d -name .git | xargs rm -dv rm: `./uploader/.git' を削除できません: ディレクトリは空ではありません rm: `./database/src/repo/create/.git' を削除できません: ディレクトリは空ではありません
-r
で再帰、-f
で警告なし。これでディレクトリ削除できる。ついでに-v
で表示。
$ find . -type d -name .git | xargs sudo rm -rfv `./uploader/.git/index' を削除しました ...
以下で.git
フォルダがもう存在しないことを確認した。
$ find . -type d -name .git
エラー
find: パス名は評価式の前に置かなければいけません
find: パス名は評価式の前に置かなければいけません
NG...
find . -name *.py
OK!
find . -name "*.py"
ワイルドカードを使うときはダブルクォーテーションで囲わないとエラーになる。
そのようなファイルやディレクトリはありません(No such file or directory)
ファイルパスに半角スペースが含まれていると1つの文字列(パス)として認識してくれない。shell文脈では半角スペースで区切られてしまうから。
【linux】 スペースを含むファイル名を find | xargs で使う方法 at softelメモ
NG...
$ find . -name "*.py" | xargs grep 'database.src.Data'
OK!
$ find . -name "*.py" -print0 | xargs -0 grep 'database.src.Data'
所感
Windowsを使っていたころは秀丸のgrep置換を使っていた。GUIだったし、正規表現を調べれば簡単だった。
Linuxではいちいちコマンドを調べているから一向に進まない。秀丸環境は最強だった。
秀丸
- 置換(正規表現), grep検索, grep置換
- マクロ(罫線引きや文字数カウントなど)
- 記憶と実行(秀丸上で実行したことを記憶し、そのまま実行できる。ショートカット一発で。)
- 拡張子別の設定(.pyはTABキー押下でスペースに置き換え、ほかはハードタブなど)
秀丸ファイラ
- 前回終了状態の復元
- ファイルパスコピー(ショートカット一発)
Linuxにしてから作業効率がとてつもなく下がっている。Windowsの文字コード問題から解放されたのは幸せだが、秀丸環境の喪失は痛い。viを使っていないからか。