fzfでターミナル作業を効率化

fzfとは

fzfとはざっくり言うと出力結果を一覧で表示して選択出来るUIを提供してくれて、その中で曖昧検索が出来て選択したものを抽出して出力してくれるものです。ファジーファインダーと呼ばれるツールの一つです。普段のコマンドと組み合わせることで作業を効率化出来るのでとりあえず入れておいて損はないです。

以前fzf.vimというVimプラグインを紹介しましたが、今回はfzfをターミナルに導入してみたいと思います。ターミナルでの作業が楽になるような使い方を色々とまとめてみましたので~/.zshrcに記述して使ってみて下さい。

fzfインストール

Macのzshが動作保証環境です。下記のコマンドでfzfをインストールして下さい。

$ brew install fzf

Vimでfzfを使う

ファイル検索

fviと入力した時にVimで開くファイルをカレントディレクトリからfzfで検索可能にします。

fvi() {
  local file
  file=$(find . | fzf)
  vi "$file"
}

全文検索

fvir [pattern]と入力した時に[pattern]を含むファイルをカレントディレクトリからfzfで検索して、Vimでその内の選択したファイルを開く。

fvir() {
  local file
  file=$(rg $1 | fzf | cut -d ":" -f 1)
  vim $file
}

これはrigrepを利用しているので先にrgコマンドを使えるようにする必要があります。

$ brew install rigrep

Gitでfzfを使う

fzfで行うブランチ移動

fgcgit checkout 【ブランチ】のブランチ移動を選択式にします。

fgc() {
  local branches branch
  branches=$(git branch -vv) &&
  branch=$(echo "$branches" | fzf +m) &&
  git checkout $(echo "$branch" | awk '{print $1}' | sed "s/.* //")
}

fzfでコミットチェックアウト

fgclgit log --onelineで取得出来るSHAからコミットにチェックアウトするのを選択式にします。

fgcl() {
  local commits commit
  commits=$(git log --color=always --pretty=oneline --abbrev-commit --reverse) &&
  commit=$(echo "$commits" | fzf --tac +s +m -e --ansi --reverse) &&
  echo -n $(echo "$commit" | sed "s/ .*//") | xargs git checkout
}

Dockerでfzfを使う

fzfでDockerコンテナにログイン

fdedocker psの出力結果の中から選択してdocker exec -it 【コンテナID】 /bin/bashでコンテナの中にログインします。ログインシェルがbashじゃない場合はそこだけ変更が必要です。

fde() {
  local cid
  cid=$(docker ps | sed 1d | fzf -q "$1" | awk '{print $1}')
  [ -n "$cid" ] && docker exec -it "$cid" /bin/bash
}

fzfでDockerコンテナのログ取得

fdldocker ps -aの出力結果の中から選択してdocker logsでコンテナのログを出力します。下記では直近200行からリアルタイム表示させるオプションとなっています。

fdl() {
  local cid
  cid=$(docker ps -a | sed 1d | fzf -q "$1" | awk '{print $1}')
  [ -n "$cid" ] && docker logs -f --tail=200 "$cid"
}

fzfでDockerコンテナ再起動

fdrdocker ps -aの出力結果の中から選択してdocker restartを実行してコンテナを再起動します。fzfコマンドのオプションで-mを付与すると<Tab><Shift + Tab>で複数選択が可能なので、複数コンテナを一括で再起動出来るようにしています。

fdr() {
  local cid
  cid=$(docker ps -a | sed 1d | fzf -m -q "$1" | awk '{print $1}')
  [ -n "$cid" ] && echo $cid | xargs docker restart
}

fzfでDockerコンテナ削除

fdrmでコンテナを選択削除出来るようにします。ロジックはfdrと同じで最後のdockerのコマンドだけdocker rm -fにしています。

fdrm() {
  local cid
  cid=$(docker ps -a | sed 1d | fzf -m -q "$1" | awk '{print $1}')
  [ -n "$cid" ] && echo $cid | xargs docker rm -f
}

Chromeでfzfを使う

fzfでChromeのブックマークバーを検索して開く

fcbを入力するとブックマークバーに登録したブックマークを開きます。

fcb() {
  bookmarks_path=~/Library/Application\ Support/Google/Chrome/Default/Bookmarks
  jq_script='
     def ancestors: while(. | length >= 2; del(.[-1,-2]));
     . as $in | paths(.url?) as $key | $in | getpath($key) | {name,url, path: [$key[0:-2] | ancestors as $a | $in | getpath($a) | .name?] | reverse | join("/") } | .path + "/" + .name + "\t" + .url'
 jq -r "$jq_script" < "$bookmarks_path" \
     | sed -E $'s/(.*)\t(.*)/\\1\t\x1b[36m\\2\x1b[m/g' \
     | fzf --ansi \
     | cut -d$'\t' -f2 \
     | xargs open
}

複数ユーザを登録している場合は下記の通りbookmarks_pathを変更すると同様に開けます。fcb2でユーザ2のブックマークを開けます。

fcb2() {
  bookmarks_path=~/Library/Application\ Support/Google/Chrome/Profile\ 1/Bookmarks
  jq_script='
     def ancestors: while(. | length >= 2; del(.[-1,-2]));
     . as $in | paths(.url?) as $key | $in | getpath($key) | {name,url, path: [$key[0:-2] | ancestors as $a | $in | getpath($a) | .name?] | reverse | join("/") } | .path + "/" + .name + "\t" + .url'
 jq -r "$jq_script" < "$bookmarks_path" \
     | sed -E $'s/(.*)\t(.*)/\\1\t\x1b[36m\\2\x1b[m/g' \
     | fzf --ansi \
     | cut -d$'\t' -f2 \
     | xargs open
}

fzfでChromeの検索履歴を検索する

fchと入力するとChromeの検索履歴をfzfで曖昧検索をして開きます。複数ユーザを登録している場合のパスの指定は先程のブックマークと同じように対応して下さい。

fch() {
  local cols sep google_history open
  cols=$(( COLUMNS / 3 ))
  sep='{::}'
  if [ "$(uname)" = "Darwin" ]; then
    google_history="$HOME/Library/Application Support/Google/Chrome/Default/History"
    open=open
  else
    google_history="$HOME/.config/google-chrome/Default/History"
    open=xdg-open
  fi
  cp -f "$google_history" /tmp/h
  sqlite3 -separator $sep /tmp/h \
    "select substr(title, 1, $cols), url
     from urls order by last_visit_time desc" |
  awk -F $sep '{printf "%-'$cols's  \x1b[36m%s\x1b[m\n", $1, $2}' |
  fzf --ansi --multi | sed 's#.*\(https*://\)#\1#' | xargs $open > /dev/null 2> /dev/null
}

Bash環境でも

CentOS7でもよく開発をするのでbash環境にもfzfを導入する方法もついでにまとめておきます。まず下記コマンドでfzfリポジトリをクローンして下さい。

$ git clone https://github.com/junegunn/fzf.git ~/.fzf

次にinstallコマンドを実行して下さい。途中.bashrcを更新しますか?と聞かれるので手を加えられたくない方はnoを入力して下さい。

$ ~/.fzf/install

fzfのインストールが成功した場合.fzf.bashが作成されます。このファイルを起動時に読み込まれるように.bashrcに下記を記述して下さい。

source ~/.fzf.bash

これでCentOS7でもfzfを使用できるようになりました。ちなみに先述で紹介した関数はbashでもそのまま使用できます。

終わりに

為になるfzfの使い方はありましたでしょうか。上では自分の普段の作業を対象にfzfを使用した例を取り上げているのですが一つでも皆様のお役に立てるものがあれば嬉しいです。

またこちらには開発者の方の使用例が記載されておりますので興味の有る方は御覧下さい。きっと勉強になると思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA