ShellScript
Linux

ディレクトリにタグ付けして移動を簡単にするスクリプト

ディレクトリを細かく分けていたりすると、ディレクトリ構造が深くなりcdコマンドでのディレクトリ移動が面倒くさくなることが多かったため、簡単に指定したディレクトリに移動できる
コマンドを作成してみた。この記事は、その構成のメモ。

作成したスクリプトは https://github.com/x-color/jump-sh に置いてある。

demo.gif

構成

構成は大きく分けて以下の通り。

  1. オプション解析
  2. 各オプションの処理
  3. ディレクトリ移動処理

オプション解析

オプション解析には、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コマンドを実行したところでカレントディレクトリが移動しないことに気がついた...