Linuxターミナル、コマンドtips その2: ファイルを見つける(locate, find)、ファイルの中身を調べる(grep)
(2019/06/29追記) 実践的、網羅的かつ簡潔にまとまったドキュメントを見つけたのでメモ(日本語訳もある)*1。
このtipsはこれからLinuxを使っていく必要がある人、特に端末操作に苦戦している人、もしくは端末操作に対して嫌悪感すら抱いている人に向けて書いたものです.作成の経緯はその1の冒頭および注釈に書きました.
前回の話題
- ターミナル関係のショートカットキー
- コマンド入力(タブ補完、インクリメンタルサーチ)
- ディレクトリ構造の把握(tree)、ディレクトリの移動(cd)
- ファイル一覧表示(ls)
linuxターミナル、コマンドtips その1: キーボードショートカットとディレクトリの移動
今回の話題
- ファイルを見つける(locate, find)
- ファイルの中身を調べる(grep)
余談:ターミナルを縦に割ることはできないのか? -> tmux
tmuxは、分割可能かつ出し入れ可能なターミナル
縦横にターミナルを割ることも大きな特徴だが、出し、入れ(アタッチ、デタッチ)できることもtmuxの大きな特徴.例えば、ssh先のマシンでプログラムを実行したら、(バックグラウンド実行するなどしないと)処理が終わるまでターミナルを開きっぱなしにしておく必要がある..tmuxを使えば、リモート先でプログラム実行中のtmuxターミナルを一旦デタッチしておいて、後からアタッチして続きを確認するなどといったことが可能となる(もちろんローカルでも同じことができる).
セッション、ウィンドウ、ペインなどの概念があるが、これについては以下のページにわかりやすい図がある.
GNU Screen ライクなターミナルマルチプレクサ「tmux」を使う
各種コマンドについては、例えば以下を参考に.
以下の流れでひと通りの動作を確認
$ sudo apt-get install tmux $ tmux C-b % #縦割り C-b " #横割り C-b o #ペインの移動 C-b c #ウィンドウ作成 C-b w #ウィンドウ一覧表示、移動 C-b n #次のウィンドウに移動 C-b p #前のウィンドウに移動 C-b d #デタッチ $ tmux a #アタッチ
余談:TMTOWTDI 「やり方は1つじゃない」-> history | grep 'key word'
インクリメンタルサーチで過去のコマンドを取り出す以外に、historyコマンドに対してgrepするやり方
インクリメンタルサーチ
ctrl+r
ctrl+r
を押す度に別の候補を表示
ctrl+r #文字を入力
入力した文字にマッチする過去のコマンドを候補として表示、ctrl+r
を押す度に遡る
history | grep 'key word'
例えば、過去に複数回apt-getをやっていて、そのうちの1つをもう一度実行したい場合、
$ history | grep apt-get
該当する履歴の番号(例えば1002だとして)を選んで、
$ !1002
とすれば、該当コマンドを実行できる
ファイルを見つける:locate, find
locateコマンド
指定したファイル名のファイルパスをファイルシステム全体から検索して表示する
例えば、stdio.hというファイルがどこにあるのか知りたい時、
$ locate 'stdio.h' /usr/include/stdio.h /usr/include/c++/4.6/tr1/stdio.h /usr/include/c++/4.7/tr1/stdio.h /usr/include/x86_64-linux-gnu/bits/stdio.h /usr/lib/perl/5.14.2/CORE/nostdio.h
定期的に更新されるデータベースを探索するので、高速に動作する.どのディレクトリ以下にあるのかも検討がつかない場合に特に重宝する.
sudo updatedb
新しいファイルなどは、データベースに登録されていない可能性があるので、その場合はlocate
コマンドを叩く前に以下を実行しておく
$ sudo updatedb
findコマンド
以下の例は基本的に下記URLの焼き直しなので、詳しくは下記URLを参照
指定したディレクトリ以下を検索する
$ find /usr
途中で出力を止めたかったら慌てずctrl + c
ディレクトリも含めた全てのファイルのファイルパスが一覧で表示されるはず
カレントディレクトリ以下全体を検索する
find
検索するファイル名を指定する
-nameオプションで、指定したファイル名だけを検索できる
*.cなど、ワイルドカードを使用することもできる
$ find /usr -name "stdio.h"
ファイルのタイプを指定する
-typeオプションを用いれば特定のファイルタイプのみを抽出できる
ファイルだけを検索
$ find /usr -type f
指定がない場合、ディレクトリも出力に含まれる
ディレクトリだけを検索
$ find /usr -type d
例:リストアップした全てのファイルに対してgrepをかける
$ find /usr | xargs grep 'hogehoge'
例えば、カレントディレクトリにあるファイルに対してgrepをかけたい時、
$ find | xargs grep 'hogehoge'
仮にfindで数万個のファイルが見つかったとしても動作する
例:検索したファイルを全て削除する
$ find hoge-dir/ | xargs rm
ex:src
ディレクトリ以下の.oファイルのみを削除する
find src/ -name "*.o" | xargs cp -t /tmp/
例:指定したファイルのみを別のディレクトリにまとめて{コピー|移動}する
ex:src
ディレクトリ以下の.ccファイルのみをtmp
ディレクトリ以下にコピーする
find src/ -name "*.cc" | xargs cp -t /tmp/
ex:移動したい場合
find src/ -name "*.cc" | xargs mv -t /tmp/
例:ソースコードの行数をカウントする
find src include -name "*.cc" -or -name "*.h" | xargs wc -l
複数の条件を、-or
や-and
で組み合わせることもできる
findまとめ
-typeや-nameで上手に欲しいファイルだけを抽出すれば、xargsとの組み合わせで、可能性が無限大.指定した複数のファイル全てに対して決まった操作を行いたい場合に重宝する.もちろん、rm -rf /hoge-dir
でディレクトリの中身を全部消すとか、cp -r /src-dir /dist-dir
で、ディレクトリまるごとコピーとか、細かいこと気にしない操作で済むのであればそれで構わない.
更に詳しいfindとxargsの組み合わせについて
こちらを参照
grepコマンド
以降の例は基本的に下記URLの焼き直しなので、詳しくは下記URLを参照
grepは正規表現によって指定したパターンに合致する文字列を含む行を出力する
かなり柔軟なパターンマッチができるという事実だけを覚えておき、必要に応じてググる
指定ファイルのパターンマッチ
$ grep 'hoge' target_file.txt
-e オプションで複数のパターンを一度に検索
$ grep -e 'hoge' -e 'foo' target_file.txt
行数を表示する
$ grep -n 'foo' target_file.txt
大文字小文字を区別しない
$ grep -i 'FOO' target_file.txt
指定文字以外を表示する
$ grep -v 'foo' target_file.txt
例: ソースコードの中から特定の文字列の場所を調べる
例えば、src/
以下にある全てのファイルからprintf
が書かれている行を抽出したい場合、
$ grep -inr 'printf' src/
上記はfindとの組み合わせと同じ
$ find src/ -type f | xargs grep -ni 'printf'
例: ソースコードに含まれる文字列の数をカウントする
$ grep 'bar' target_file.txt | wc -l
grepで空白文字のパターンマッチ
[[:blank:]]
か\s
で空白文字
言語やツールによって正規表現の表現方法が異なる
下記サイトによくまとまっている