シェルスクリプトの関数の仕組みを利用して新しいコマンドを追加する

シェルスクリプトの関数の仕組みを利用すると、簡易的なコマンドを簡単に追加できるようになります。

パイプで繋いだコマンドを頻繁に使用する場合、関数の形にまとめておくと便利です。


シェルスクリプトの知識はほぼ使わず、関数を追加してみます。


今回はクロームブックのクロスティーニやラズベリーパイの標準のシェルのBash(Bourne Shell)に関数を追加してみます。




はじめにシェルスクリプトの仕組みから見ていきます。

下記コマンドで引数の値を確認できる関数を追加します。


$ micro ~/.bashrc

.bashrcの末尾に下記のコードを追加します。


function fn(){
	echo $0 $1
}

※functionの記述は省略可で

fn(){
	echo $0 $1
}

のように書くこともできます。


$ source ~/.bashrc

でBashの設定を再読み込みします。


追加しましたfnを実行してみます。

$ fn
-bash

が出力されます。


続いて、

$ fn hoge
-bash hoge

が出力されます。


.bashrc内で追加しました関数の $0 と $1 は引数に置換されます。

今回であれば、$0はシェルスクリプト名になり、今回は-bashになります。

$1はコマンドの次に追加しました引数になりまして、今回であれば hoge になります。




アプリの開発が進んでいきますと、任意のフォルダ(ディレクトリ)のみのファイルの構造(例えば、プラグインのファイル構造)を確認したいことがあります。


確認したいフォルダ(ディレクトリ)に移動して、tree コマンドを実行するといったことは面倒なので、

$ tree $(find ./ -type d -name "find-fzf" | fzf)

※find-fzfというディレクトリ名のファイル構造を調べるコマンド

というコマンドを頻繁に実行します。

※fzfのインストールは下記ページを参考にしてください。

Microでシェルモードを使ってみる


このコマンドを関数として追加しておきます。

fzfの結果をtreeに渡すということで、ftreeコマンドにします。


$ micro ~/.bashrc

.bashrcの末尾に下記のコマンドを追加します。

ftree(){
	tree $(find ./ -type d -name "*$1*" | fzf)
}

※"*$1*"にすることで、コマンド実行時に引数指定したもので部分一致の検索を行えるようにします。

$ source ~/.bashrc

でBashの設定を再読み込みした後、コマンドを試してみます。

$ ftree find-fzf


fzfの実行結果が表示され、調べたいディレクトリを選択すると、

./.config/micro/plug/find-fzf
├── find.lua
├── README.md
└── repo.json

1 directory, 3 files

のような出力になりました。


他の例として、ファイル名を検索した後に対象となるファイルが配置されているディレクトリに移動する。

fcd(){
	local FILEPATH
	FILEPATH=$(find ./ -type f -name "*$1*" | fzf)
	FILEPATH=${FILEPATH%/*}
	cd $(pwd)${FILEPATH#.}
}



今回の内容のシェルスクリプトの書き方を見ていきます。


tree $(find ./ -type d -name "*$1*" | fzf)

の$(コマンド)ですが、()内で得られた結果(fzfで選択した値)を基にtreeコマンドを実行します。

※コマンド置換と呼びます


FILEPATH=$(find ./ -type f -name "*$1*" | fzf)

ですが、FILEPATHはシェル変数になりまして、変数名は大文字だけでなく、小文字、数字やアンダースコア(_)も使用可ですが、大文字で書かれているものをよく見かけますので、今回も大文字にしています。


上記コードの一行上に

local FILEPATH

がありますが、localを付けることで、FILEPATHを{}内でのみ使用可にします。

※{}内でのみ使用可の変数をローカル変数と呼びます。


変数に値を代入する時は他言語と違い=の両端のスペースは除きます。


変数の値を参照する場合は、

$FILEPATH

もしくは

${FILEPATH}

にします。


例えば、FILEPATHに代入された値を出力する場合は、

$ echo ${FILEPATH}

にします。


今回、

FILEPATH=${FILEPATH%/*}

のように変数名の後に%/*が追加されています。


変数名の横に%をつけることで、右側からパターン(今回であれば/*)に一致する最短の部分が取り除かれるという意味になりまして、

$ echo ${FILEPATH}
./workspace/mcws/mcws_blockly/main.js

の場合、

$ echo ${FILEPATH%/*}
./workspace/mcws/mcws_blockly

のようにmain.jsファイルが配置されているディレクトリのパスになります。


${変数%%/*}の%%は右側からパターンに一致する最長の部分が取り除かれることになり、

$ echo ${FILEPATH%%/*}

であれば、

.

になります。


${FILEPATH#.}

は左側からパターン(今回であれば.)に一致する最短の部分が取り除きます。


echo ${FILEPATH#.}

/workspace/mcws/mcws_blockly/main.js

になります。


今回は触れませんが、${変数##.}の##は左側からパターンに一致する最長の部分が取り除かれます。


最後にpwdコマンドですが、現在作業しているディレクトリを表示します。

$ echo $(pwd)
/home/pi

$ pwd
/home/pi
マインクラフト用ビジュアルエディタを開発しています。
詳しくはinunosinsi/mcws_blockly - githubをご覧ください。