コマンド履歴の検索とかディレクトリ移動について(Bash)
【Shell入門】一生触るターミナル操作を強化しておこうぜ! この動画がよかったので、自分のコマンド履歴の設定とか検索とかディレクトリ移動について(Bash)
目次
history 履歴について
履歴に関する設定(.bashrc)
# コマンドの先頭が空文字の場合と重複したコマンドは記録しない HISTCONTROL=ignoreboth:erasedups # 履歴の保存サイズ HISTSIZE=100000 HISTFILESIZE=100000 # 前方一致検索。Ctrl+n か Ctrl+p で履歴をたどるときに、 # 例えば ls と打ってから Ctrl+p すると ls の履歴のみたどれる bind '"\C-n": history-search-forward' bind '"\C-p": history-search-backward'
Ctrl + r の強化
peco (fzfでもいいけど) 使って Ctrl + r の履歴検索を強化する。リリースページ からバイナリダウンロードしてもいいし clone して go build して /usr/local/bin に放り込んでもいいけど apt が楽なので
sudo apt install peco
インストールしたら .bashrc とかに以下を記述して Ctrl+r の履歴検索を強化する。これも --query $READLINE_LINE
で途中まで入力した文字で前方一致検索できる
func_peco_history() { local v=$(HISTTIMEFORMAT= history | sed -E s/^\ *[0-9]\+\ \+// \ | sort -r | uniq | peco --query "$READLINE_LINE") READLINE_LINE="$v" READLINE_POINT=${#v} } bind -x '"\C-r": func_peco_history'
ディレクトリの移動について
ディレクトリ移動はコマンド履歴の検索と以下の2つの方法を使う。よく使うパスが長いディレクトリなんかは alias
とか設定しとけばいいと思う。
ディレクトリの検索
peco を使って find コマンドの結果から絞り込む。.bashrc
とかに以下を書いて pcd
する。フィルタを Regexp
にしてるのは project$
のように $
を付けるとそれ以下の階層を除外できてよい。使用頻度少ないけど
pcd() { local c="." [ -n "$1" ] && c="$1" local v=$(find $c -type d -and ! -regex '.*/node_modules/.*' 2> /dev/null | peco --initial-filter=Regexp) [ -d "$v" ] && cd "$v" }
cd コマンドの強化
間違いなく この記事 だと思うけど、その昔に読んでからずっと使ってる便利な cd
コマンド拡張
func_enhanced_cd() { local x2 the_new_dir adir index local -i cnt if [[ $1 == "--" ]]; then dirs -v return 0 fi the_new_dir=$1 [[ -z $1 ]] && the_new_dir=$HOME if [[ ${the_new_dir:0:1} == '-' ]]; then # # Extract dir N from dirs index=${the_new_dir:1} [[ -z $index ]] && index=1 adir=$(dirs +$index) [[ -z $adir ]] && return 1 the_new_dir=$adir fi # # '~' has to be substituted by ${HOME} [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}" # # Now change to the new dir and add to the top of the stack pushd "${the_new_dir}" > /dev/null [[ $? -ne 0 ]] && return 1 the_new_dir=$(pwd) # # Trim down everything beyond 11th entry popd -n +11 2> /dev/null 1> /dev/null # # Remove any other occurence of this dir, skipping the top of the stack for ((cnt = 1; cnt <= 10; cnt++)); do x2=$(dirs +${cnt} 2> /dev/null) [[ $? -ne 0 ]] && return 0 [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}" if [[ "${x2}" == "${the_new_dir}" ]]; then popd -n +$cnt 2> /dev/null 1> /dev/null cnt=cnt-1 fi done return 0 } alias cd=func_enhanced_cd
使い方
コマンドに
--
を付けると、最近 cd した履歴が表示される$ cd -- 0 ~/foo 1 ~/bar 2 ~/baz
履歴の左にある番号を
-1
のように指定することで cd できる$ cd -1
edit-command-line の自作
冒頭の動画見てて zsh
の edit-command-line
というのが便利そうだったので bash
でもやりたいと思って作った。 alt か esc キーのあとに e を押せば書きかけのコマンドを vim で編集できる。
func_edit_command_line() { # 何か入力してないと起動しない [ -z "$READLINE_LINE" ] && return 0 # EDITOR 変数が空なことがあるのか知らんけど一応 [ -z "$EDITOR" ] && EDITOR='/usr/bin/vim' # /tmp ディレクトリに一時ファイルを作ってそれを編集 local RAMDOM_STR=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) local TMP_FILE="/tmp/$RAMDOM_STR" echo "$READLINE_LINE" > "$TMP_FILE" && $EDITOR "$TMP_FILE" if [ $? -ne 0 ]; then [ -f "$TMP_FILE" ] && rm -f "$TMP_FILE" return $? fi local TMP_STR=$(cat $TMP_FILE) if [ -n "$TMP_STR" ]; then # エディタで編集した内容を戻す READLINE_LINE="$TMP_STR" READLINE_POINT="${#READLINE_LINE}" fi [ -f "$TMP_FILE" ] && rm -f "$TMP_FILE" return 0 } bind -x '"\ee": func_edit_command_line'
書き終わってから何となく bind -l
で関数見たら edit-and-execute-command
とかある。bind -P
見たら \C-x\C-e
とある。つまり Ctrl+x Ctrl+e
で同じことできる。エディタ閉じたら即実行されるとか違いはあるけど