rcmdnk's blog

減らす技術 The Power of LESS

ターミナルでドキュメントを開く手軽なコマンドのlessですが、 小さなものならcatで良かったり、 サイズがそこまで大きく無ければvim等のエディタで開いてみてしまったりすることが多いです。

というのもlessの機能を余り知らないのでvimなどで見た方が色々と便利だったりするので。

しかしlessも実は結構高機能で便利だったりするので知っていると 使えることも結構あります。

その辺の一歩踏み込んだlessの使い方について。

less

lessはMark Nudelman氏によって書かれたもので、今は GNU Projectの一つです。

Less (greenwoodsoftware)

less - GNU Project - Free Software Foundation

lessはBSD版が無いのでMacなどのBSDな環境でもLinuxなどと同じlessが入っています。

なので以下の話は基本的にどのシステムでも同じ事が言えます。

元々moreという、ファイルの中身を順に表示していくプログラムがありましたが、 これは上に戻る事ができないもので、 後ろに戻れたりする様により使い勝手を良くしたものがlessになります。

なので(?)、ヘルプを開くと

NAME
       less - opposite of more

と書いてあります。

デフォルトの表示用のコマンドとして設定しているプログラム も多くあり(manの表示やgit logの表示など)、 直接lessを叩かなくても使ってる機会は結構多いと思います。

manとかがlessになってない場合は PAGERと言う環境変数がless以外のものに設定されてるはずです。

export PAGER=less

とするとlessになります。

Vimなどのエディタより機能が少ない分、表示も高速なので 特に大きなファイルを開く際には見るだけならlessのが便利です。

また、コマンドの出力が長い時、パイプでlessに渡して読む、という使い方も良くあると思います。

何かのコマンドのヘルプを見たい時、1画面に収まらないようなことがあるので、そういった場合は

$ example_cmd --help | less

みたいなことを良くやります。

操作方法はviに従う様な形でJで下、kで上に進む様になっています。 検索等もviの操作と同じです(/で開始、Nで次へ、など)。 後はQで終了、位を覚えておけばとりあえずは使えます。

困ったらHを押すとヘルプが出ます。 (たまにvi(vim)の操作と間違えて押して出てきてしまうときがある。。。)

ちなみに今使ってるMacだと/usr/bin/moreは実際にはlessになっています。 ハードリンクとかでも無いみたいですが、 more --versionとかするとlessのバージョン情報が出ます。

以前はマルチバイト表示ができなかったので、 jless (今はもう元ページがない) やさらに色々な機能が加わった lv と言ったコマンドをインストールして日本語ファイル等を開く必要がありました。

ですが現在のlessであれば日本語が普通に使える環境下であれば 大概の場合日本語表示も問題なく出来る様になっていると思います。

オプションのプレセット指定

LESSという環境変数にオプションを指定しておくと less実行時にそのオプションを付けて実行してくれます。

.bashrc
1
export LESS='-I -R -M -W -x2'

今使っているのはこんな感じ。

  • -I: 検索時に小文字で書いた場合大文字小文字を区別しない。大文字を入れると区別する。
  • -R: ANSIカラーコードなどを理解して色付き表示に。
  • -M: 現在表示中のファイル名や行数をプロンプトに表示。
  • -W: 2行以上進んだ時、新たに表示された最初の行を一時的にハイライトする。
  • -x<number>: タブ記号をnumber分のスペースとして表示。

他のオプションについてはman lessで。

-Mに関して、現在表示されている最初の行と最後の行の行数の表示がされ、 さらに全体の行数と今いる部分が何%目にあるのか、という表示がされます。

ただし、下に書くsource-highlightを使っていると 最初に表示した時点では全行数と%表示がされず、 一度一番下まで行くと表示される様になります。

表示中にオプションを切り替える

lessは表示を開始した後でもオプションを切り替える事が出来ます。

上にあげてないオプションで-Nという、各行の行数を表示するオプションがありますが、 lessを開始後、- Shift-Nを押してReturnを押せば 行数が表示されます。 もう一度押すと消えます。

シンタックスハイライト(source-hilight、ついでにlesspipe.shについて)

Vim等のエディターではソースコードなどに色を付けて分かりやすく表示することが出来ますが、 lessでもsource-highlightを使うと同じ様な事が出来ます。

GNU Source-highlight - GNU Project - Free Software Foundation (FSF)

インストールはMacでHomebrew、

$ brew install source-highlight

Linuxでyumやapt-get

$ yum install source-highlight
$ apt-get install source-highlight

で入れられます。

もしくは公式マニュアル にある様に手動で。

インストールしたら、/usr/local/bin(もしくは指定したパス)に src-hilite-lesspipe.shというスクリプトが入っていると思います。

これを

export LESSOPEN="| src-hilite-lesspipe.sh %s"
export LESS='-R'

の様に.bashrcなどで設定するとシンタックスハイライトをつけた状態でソースコードなどがless出来る様になります。

LESSOPENはファイルなどを開く際に一度何らかの手を加えるためのコマンドを指定します。 src-hilite-lesspipe.shはファイルの種類などを見て適時シンタックスハイライトを 与えてくれるスクリプトです。

スクリプトの指定時の最初に|を与えるのはこれがパイプ処理によるものだと伝えるためです。 %slessに与えるファイル名になります。 もっと詳しくはman lessで。

LESSの方は上にも書いたオプションセットで自由に設定して良いですが、-Rだけは忘れない様に。 これを付けないとESC [...mの表示が沢山出てしまう状態になります。

さて、このsrc-hilite-lesspipe.shの中身を見てみると

src-hilite-lesspipe.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/sh

for source in "$@"; do
    case $source in
  *ChangeLog|*changelog) 
        source-highlight --failsafe -f esc --lang-def=changelog.lang --style-file=esc.style -i "$source" ;;
  *Makefile|*makefile) 
        source-highlight --failsafe -f esc --lang-def=makefile.lang --style-file=esc.style -i "$source" ;;
  *.tar|*.tgz|*.gz|*.bz2|*.xz)
        lesspipe "$source" ;;
        *) source-highlight --failsafe --infer-lang -f esc --style-file=esc.style -i "$source" ;;
    esac
done

こんな感じのスクリプトです。

中身を見るとsource-highlightを使ってハイライト付きの出力を作っていることが分かります。

source-hilightは入力テキストを色々なフォーマットでシンタックスハイライトを付けた 状態で出力してくれるプログラムです。

-f escでハイライトをエスケープシーケンスの形で出力してくれます。 他にもhtmllatexといった出力も可能で、ファイルに保存すれば ブラウザでハイライト付きのコードを見たりすることも出来ます。

スクリプトの中ではいくつか拡張子の種類によって場合分けをしていますが、 tar等の所ではsource-hilightを使わずにlesspipeというスクリプトを呼んでいる事が分かります。

lesspipeは圧縮ファイル等のバイナリファイルの中身を表示してくれるスクリプトで これをかます事でlessで圧縮ファイルの中身を見ることが出来ます。

lesspipe, an addon for the browser less

なんですが、このlesspipeはどのシステムに入っているものではないため ここでエラーが出てしまう事があります。

$ less example.tar.gz
/usr/local/bin/src-hilite-lesspipe.sh: line 10: lesspipe: command not found
"example.tar.gz" may be a binary file.  See it anyway?

みたいな。 ここでyを押せば強制的に見ることは出来ますが、バイナリファイルを直接見るので良くわからない表示が出るだけです。

さらに、システムによってはlesspipeが予め入っているものもありますが、 入っているスクリプトの名前はlesspipeではなくlesspipe.shであることがほとんどです(少なくとも見れる範囲では全部)。

lesspipe.shが予め入っている環境では、

/etc/profile.d/less.sh
1
[ -x /usr/bin/lesspipe.sh ] && export LESSOPEN="${LESSOPEN-||/usr/bin/lesspipe.sh %s}"

というスクリプトが入っていて、これが/etc/bashrcから呼ばれる様になっています。

通常、個人の.bashrc

if [ -r "/etc/bashrc" ];then
  source /etc/bashrc
fi

みたいな感じで最初にシステムのbashrcを読み込むと思いますが、 これによってLESSOPENが予めlesspipe.shに指定してある場合があります。

なぜsrc-hilite-lesspipe.shの中でlesspipe.shではなくてlesspipeが 指定されているのかよく分かりませんが、 これだとせっかくのlesspipe機能が使えないので、

$HOME/usr/bin/my_lesspipe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env bash
for source in "$@"; do
  case $source in
    *ChangeLog|*changelog)
      source-highlight --failsafe -f esc --lang-def=changelog.lang --style-file=esc.style -i "$source" ;;
    *Makefile|*makefile)
      source-highlight --failsafe -f esc --lang-def=makefile.lang --style-file=esc.style -i "$source" ;;
    *.tar|*.tgz|*.gz|*.bz2|*.xz)
      if type -a lesspipe.sh >& /dev/null;then
        lesspipe.sh "$source"
      elif type -a lesspipe >& /dev/null;then
        lesspipe "$source"
      fi
      ;;
    *) source-highlight --failsafe --infer-lang -f esc --style-file=esc.style -i "$source" ;;
  esac
done

みたいなスクリプトを作って

.bashrc
1
2
3
4
5
6
7
8
export LESS='-I -R -M -W -x2'
if type -a source-highlight >& /dev/null;then
  if type -a my_lesspipe >& /dev/null;then
    export LESSOPEN='| my_lesspipe %s'
  elif type -a src-hilite-lesspipe.sh >& /dev/null;then
    export LESSOPEN='| src-hilite-lesspipe.sh %s'
  fi
fi

みたいな感じで設定しておくとlesspipeもきちんと使える様になります。

LESSOPEN.bashrc内で関数を作ってそれを与えてみようとも思いましたが、 その場合command not foundになってしまって上手く行きませんでした。 commnadコマンドで探せるPATHにある(もしくはフルパス指定で見える)コマンドファイルでないと駄目な様です。

なのでちょっと面倒ですがpipeファイルを用意して置いておく必要があります。

ソースコードとかをちょっと見たい時、エディタで見るほどでもなくても 色付きで見たいから、という理由でエディタで開く事が多いと思いますが、 lessでも色付きで開ければパッと見るにはlessのが便利だったりすることも。

ただし、上のオプションのところや下にもありますが、 いくつか弊害が起こるのでちょっと注意が必要です。

途中からエディタで開く

lessで開いても途中から編集したくなるときがあるかと思います。

そんな時はvを押せばデフォルトエディタ(VISUALもしくはEDITORで指定されたエディタ、両方指定されてない場合はvi) で開き直します。

この場合、エディタを終了すると再びlessに戻ります。

複数のファイルを扱う

lessでは複数のファイルを同時に開いて切り替えて見ることが出来ます。

$ cat a.txt
aaa
$ cat b.txt
bbb
$ less a.txt b.txt # or *.txt
aaa
a.txt (file 1 of 2) lines 1-1/1 (END) - Next: b.txt

みたいな感じで始まり、:nで次のファイル、:pで前のファイルに移ります。

Vimのコマンドラインモードみたいな感じですが、 Enterを押さないで nとかを打った瞬間にファイルの移動が完了します。

  • :n: 次のファイルを開く
  • :p: 前のファイルを開く
  • :x: 最初のファイルを開く
  • :d: 現在のファイルをリストから削除する
  • :e <file>: 新たに<file>をリストに加えて開く

辺りが関連するコマンド。 :eだけは最後にEenterを押して決定する必要があります。

:nを押し続けて最後のファイルに行くともう一度押しても最初のファイルには戻りません。 最初のファイルで:pを押しても最後のファイルには行きません。

tail -fの代わりに使う

数年前ですが、下のブログがちょっと話題になってたless +F

Stop using tail -f (mostly)

ログなんかを監視する時にtail -f <file>とやると 新たな書き込みを表示し続ける様なことをが出来ます。

これと同じ事がlessでも出来て、

$ less +F a.txt
aaa
Waiting for data... (interrupt to abort)

とすると、ファイルへの追加記述をリアルタイムで表示してくれます。

さらに、ここでCtrl-Cを押すと 通常のless状態になってファイルの中身を読むことが出来ます。

通常のless状態からはShift-F でまたtail -fの様な状態に戻れます。

上のブログやそれに対する反応もtailなんて使わずにlessのが良いよということなんですが、 個人的にはtailのが使いやすいかな、と思います。

終了数時にtail -fならCtrl-Cで終わりますが、 less +FだとさらにQを押す必要があります。

必ずlessの通常モードで見る、と言った場合以外はむしろデメリットです。

それからlessの方が複雑なプログラムだからか、 実際にやってみるとlessの方はちょっとタイムラグがあります。

後、+Fが両方Shiftが必要という所も地味にだるい。 なのでalias t="less +F"なんてやってもみましたが、 結局Ctrl-Cですぐ終わらないのが嫌で使ってません。

ただ、通常通りファイルを開いてもShift-F を押せば追記を表示するモードになるので、 ログをlessで開いた後に追記がないかな、ということで使うことはたまにあるので 覚えておいて損はしないと思います

なんですが、上に書いたsource-highlightを適用すると +Fで始めても途中でShift-Fしても追記を表示してくれない状態になってしまいます。

この場合、-Lオプションを加えるとLESSOPENを無視する様になるので

alias t='less -L +F'

みたいにするとsource-highlightを入れていてもt <file>とすることでtailf -f機能を使えます。

ただし通常のlessで始めてしまうと途中から追記状態にすることは出来ません。

見ているものが元々のファイルではなくてsource-hilightのアウトプットなため。 なので始めてから-Lを打っても追記を表示させることは出来ません。

上のブログの中に複数のファイルを同時に監視したい時は lessだと出来ない(正確には上に書いた複数ファイルを開いた状態で移動してShift-Fをして、とかしないといけない)、という事がありますが、 tailでもその都度新しい追加文字とそのファイル名が表示される様な形になります。

そんな時はmultitailxtailと言った複数ファイル監視に特化した ソフトウェアを使うと便利だったりします。

Sponsored Links
Sponsored Links

« Homebrewで多くインストールされているパッケージ stow-get: Stowを使ったパッケージマネージャー »

}