オリジナルのコマンドを作ろう

研究でプログラムを書いたり走らせたりするときにはコマンドラインをよく使うと思います。例えばカレントディレクトリから目的のディレクトリに移りpythonを実行、あるいはsshでサーバーに接続してdockerの起動…複数のコマンドを打たねばなりません。

プログラムというのは単純なもの、繰り返し行われるものに非常に相性がよく、そういったものほど簡単に書くことができます。またそれがコマンドラインだけなら同じ考え方で、オリジナルのコマンドを作っていつもやる作業を単純にまとめることができます。今回は例を取りながら、オリジナルのコマンドを作って作業を単純化させてしまいましょう。

エイリアス

頻出コマンドlsは開発中に何度も何度も打つコマンドです。しかしながらlsだけで打つよりはls -als -lhなどのオプションを付けることが多いでしょう。よく使用するコマンドならオプションを毎回打つのはめんどくさくなります。そこで、このコマンドに別名を与えてあげるのです。それがエイリアスというものです。

実際にls -lhFコマンドをllというエイリアスにしてみましょう。まずはllコマンドが何に割り当てられているかを確認しましょう。

alias

この場合、下から2番目にll = 'ls -alF'の文字がありますね。即ち、オプションは「隠しファイル含め・詳細に・ディレクトリや実行ファイル情報を付加」になっています。これでも十分使えるのですが、-aオプションを-hオプションに変えて、ファイルサイズをMB単位でわかりやすく表示しましょう。sudoは権限が必要でログイン時のパスワードを打つ必要があります。

sudo vi ~/.bashrc

viという少し特殊なエディタを使います。どの環境にも最初から入っているはずです。
開くと先頭にカーソルがあるはずですが、矢印キーやHJKLキーを使ってそれっぽいものを見つけましょう。

それっぽいですね。こういった記述がない場合もあります。その際は一番下に新しく書き込めばOKです。書き込みにはまずカーソルの位置でIキーないしOキーを打って「Insertモード」に入らねばなりません。モードに入ったらalias ll ='ls -hlF'と編集・追加します。
編集後、EscキーでInsertモードから抜けます(Normalモード)。その状態で:wqを打ってエンターです。これで保存されます。少し癖のあるエディタですが、慣れればイージーです。

保存しただけでは適用されません。

まだls -alFの結果が出ています。そこで改めて設定を読み込みます(次回からはログイン時に自動で読み込まれます)

source ~/.bashrc

./(カレントディレクトリ)と../(親ディレクトリ)を非表示にして、ファイルサイズがわかりやすくなりました。

ペェソンを使っぞ!

では上記のような感じで自分の考えた名前のコマンドが期待した動きをしてくれることがわかったので、いよいよシェルスクリプトとPythonを使ってより高度な自動化をしましょう。まあ自動でやってくれるのはコマンドってよりPythonのおかげなんですけどね。
自作のコマンドを作るにあたって、それを格納するディレクトリを先に用意しておきます。

cd ~/
mkdir commands

で、ここに拡張子のないファイルを作ります。その中にシェルスクリプトで期待する動作を書き込んでいきます。ここでは簡単に、論文を読むのによく使うサイトを開く、ってのをやってみます。Python組み込みライブラリのwebbrowserを使いましょう。
いつもPythonで開発しているディレクトリでも何でもいいですが、そこに移動してファイルを作って(例えばcd ~/develop/python/researchからのvim webopen.pyとか)中身を書きます。中身はこんな感じで動くはずです。

import webbrowser

url_gscholar = 'http://scholar.google.co.jp'
url_transl = 'https://miraitranslate.com/trial/'
url_shaper = 'http://dream-exp.net/shaper/'

webbrowser.open(url_transl, 1, autoraise=True)
webbrowser.open(url_shaper, 2, autoraise=True)
webbrowser.open(url_gscholar, 2, autoraise=True)

簡単ですね〜Google scholarとみらい翻訳とShaperを開くだけのコードです。もちろん、普段研究で実行するコードでも動きます。

では、これをいちいちカレントディレクトリからこのファイルのあるディレクトリに移動して、あるいはpython ~/develop/python/research/webopen.pyなんて長々と入力しなくて済むようにシェルスクリプトを書いていきます。

先ほど作ったcommandsディレクトリに拡張子のないファイルを作ると書きました。やりましょう。このファイル名がコマンド名になりますので、短すぎず、他と被らずで決めましょう。

cd ~/commands
vi res

ここではコマンド名をresにしときます。その中身は下のようにします。1行目は魔法、2行目以降が処理です。

#!/bin/sh

cd ~/develop/python/research
python webopen.py

保存したらコマンドの完成です。(お察しのいい方にはPythonなんて使わなくてもopen {TARGET_URL}のシェルスクリプトだけで済んでしまうことがバレてしまいますが、あくまでもただの例なので…)

オプションを付ける

似たような動作をするけど、少し違うんだよな、でも同じコマンドで動かしたいんだよな、って時にはオプションを付けてコマンドを動かしてやれるようにします。getoptを使います。そんでオプションに何があったか忘れたときの為にUsage(HELP)を書いておきましょう。
上のコードで言ったところのpython webopen.pyあたりを下のように書き換えます。

while getopts "afh" optKey; do
  case "$optKey" in
    f)
      python webopen.py
      exit
      ;;
    a)
      python search.py
      exit
      ;;

    '-h'|'--help'|* )
      usage
      ;;
  esac
done

簡単に解説すると、getoptの引数にaとfとhが指定されています。それぞれに対応した処理を書いて言っている感じです。-f-aでは違うPythonのファイルが動くようになっているのがわかると思います。最後の'-h' | '--help' | * )はHELPのオプションあるいはa,f,hどれでもない文字がオプションとして入力されたときにusageを行う、というものです。このままではusageに何も指定していないので、書いていきます。

さっきのコードの上にfunctionを書きます。

function usage {
  cat <<EOM
Usage: $(basename "$0") [OPTION]...
  -h     Display help
  -a     Auto-Search: Open new window and search automatically
  -f     Full-Search: Search by Google Scholar with opening Translator, Shaper
EOM

  exit 2
}

これで大体はOKです。保存しておきます。

権限を与える

自作のコマンドはエイリアスと異なり、実行権限の設定を行う必要があります。作っただけでは使えないのです。

chmod u+x ~/commands/res

これでOKです。

パスを通す

さらに、ファイルを作っただけではただの中身がある箱のようなもので、それが何か認識されません。そこでパスを通すという作業をします。これは〜ですよーみたいなタグを箱に付ける、そんな感じです。そのネームタグは.bashrcというところで読み込むことができます。エイリアスのところと同じです。で、コマンドが読み込むことの出来る対象に、commandsディレクトリも追加しちゃうのです。

sudo vi ~/.bashrc

中身の最後に書き加えておきます。

export PATH=$HOME/commands:$PATH

保存して終了したら(ノーマルモードで:wq).bachrcを読み込みます。

source ~/.bashrc

これでどうでしょうか。使えるようになったはずです。

今回やってみたのは簡単な自動化だったため、別にスクリプト書いてまでやることか?って感じでしたが、いつもやる面倒作業を自動化できコマンド一つで完結できるなら良くないですか。ぜひ試してみてね。