ディレクトリを細かく分けていたりすると、ディレクトリ構造が深くなりcd
コマンドでのディレクトリ移動が面倒くさくなることが多かったため、簡単に指定したディレクトリに移動できる
コマンドを作成してみた。この記事は、その構成のメモ。
作成したスクリプトは https://github.com/x-color/jump-sh に置いてある。
構成
構成は大きく分けて以下の通り。
- オプション解析
- 各オプションの処理
- ディレクトリ移動処理
オプション解析
オプション解析には、getopts
を用いた。while
を用いることで、複数のオプションを解析している。
今回のスクリプトは関数を用いて作成しているため、環境変数を汚さないために各変数はlocal
で宣言する必要がある。これを用いないと、正常に動作しなくなることがあるため注意が必要。
local OPTIND OPTARG OPT
local _flg_add _flg_del _flg_lst _tag_add _tag_del
# Options parser
while getopts a:d:lh OPT
do
case $OPT in
"a" ) _flg_add="TRUE"
_tag_add="$OPTARG" ;;
"d" ) _flg_del="TRUE"
_tag_del="$OPTARG" ;;
"l" ) _flg_lst="TRUE" ;;
"h" ) _usage_jump
return 1 ;;
* ) _usage_jump
return 1 ;;
esac
done
各オプションの処理
タグ削除のオプション(-d)が指定
タグ削除のオプションが指定された場合は、sed
コマンドを用いてタグを保存しているファイルから、指定されたタグから始まる行を検索し削除。
# Delete bookmark
if [ "$_flg_del" = "TRUE" ]
then
# Delete
sed -i -e '/^'$_tag_del',/d' ~/.jump_tags
fi
タグ追加のオプション(-a)が指定
タグ追加のオプションが指定された場合は、カレントディレクトリのパスを取得し、指定されたタグとともにカンマ区切りでファイルに保存。
# Add tag
if [ "$_flg_add" = "TRUE" ]
then
local _dic_path=`pwd`
local _check=`grep -e '^'$_tag_add',' ~/.jump_tags`
if [ "$_check" != "" ]
then
# Error : tag is already resistered in .jump_tags
echo -e "[$_tag_add] is already registered in tags." 1>&2
return 1
else
# Add
echo "$_tag_add,$_dic_path" >> ~/.jump_tags
fi
fi
タグ一覧表示のオプション(-l)が指定
タグ一覧表示のオプションが指定された場合は、タグを保存しているファイルの内容をcolumn
コマンドで整形して表示。
# List up tags
if [ "$_flg_lst" = "TRUE" ]
then
# List up
cat ~/.jump_tags | sort | column -t -s,
fi
以下の順でタグ一覧を表示している。
1. cat
コマンドでファイルを出力。
2. sort
コマンドでタグをソート。
3. column
コマンドでカンマを区切り文字として、表形式で表示。
ディレクトリ移動処理
引数取得の準備
引数取得の前に、以下のスクリプトで指定されたオプションをすべて破棄する。これにより引数の取得が容易になる。
# Delete options
shift `expr $OPTIND - 1`
$OPTIND
は指定されたオプションの数+1の値なので、そこから1引いた分だけshift
コマンドで引数をずらすことで、オプションの破棄を行っている。
ディレクトリ移動処理
引数を取得し、指定されたタグに対応するパスをファイルから検索し、見つかった場合にディレクトリを移動する。
# Check arguments
if [ "$#" != "0" ]
then
# Jump to tag
local _dir_path=`grep -w "^$1" ~/.jump_tags | cut -d , -f2`
if [ "$_dir_path" = "" ]
then
# Error : cannot find tag in .jump_tags
echo "[$1] can not find in tags." 1>&2
return 1
else
# Jump
cd $_dir_path
fi
elif [ "$OPTIND" = "1" ]
then
# No option and no argument
_usage_jump
fi
以下の順でタグからパスを取得している。
1. grep
コマンドで指定されたタグで始まっている行をファイルから取得。この際に-w
オプションでタグが完全一致するもののみを抽出。
2. cut
コマンドで、カンマ区切りで2列目以降(パス)を取得。
あとがき
作成を始めたときは、シェルスクリプトで
#!/bin/bash
# ここまでで色々な引数処理を行う
_dir_path=指定されたタグに対応するパス
cd $_dir_path
このような感じで実装しようとしていたが、このシェルスクリプトを実行した時点でプロセスが違うので、cd
コマンドを実行したところでカレントディレクトリが移動しないことに気がついた...