web小説礼賛記

さらなる俺 TUEE をあなたに!

シェル入門 #6: CLIツールの見直し

 標準のシェルとコマンド群は、ぶっちゃけ古いです。モダンなツールを入れて、もっと便利になってしまいましょう。

Shell

 bashは古いです。普段使いのシェルは、変えたほうが便利になります。

 シェルスクリプトを書くときは、意外にbashが楽です。ネットの情報量が多いためです。

fish

 fishは非常に親切なシェルです。リアルタイムで候補を表示してくれますし、サブコマンドや省略パスにも補完が効きます。(e.g. ~/b/n-b->~/bin/n-build)。これが以外と便利です。

 ただし、本は少ないですし、検索して情報を得るのもしんどいかもしれません。

設定ファイルの書き方

 変数はsetコマンドで設定します。=は使わず、常に空白で引数を区切ります。関数やエイリアスの書き方も異なるため、自由に書くためには数十分必要でしょう。

 dotfiles fish で検索すると、人の設定ファイルが読めます。

文法の違い

  • コマンド置換は(command)です。実行順を変える機能だと思えば合理的です。
  • コマンド置換や変数展開に対しては単語分解が行われません。おかげで、余計なクォーテーション"を省くことがでいます。
  • brace{}展開に連番生成{m..n}がありません。代わりにseqのコマンド置換(seq m n)を使えますが、{0..3}.txtのような文字列を作るには、一手間かかります。(例: seq 0 3 | sed 's/$/.txt/') )

 とりあえず、これだけで十分だと思います。ドキュメントは、有名な方が翻訳してくれています。

zsh

 fishと並んで有名です。bashcshのいいとこ取りをしたシェルらしいです。調査中です。

bashでもオプションなどに補完を利かせる

 調査中です。

Emacs

 ELispを駆使する人々は、Emacsエディタ上でシェルを使うようです。(ちょっと変態的な指向ですね)。ファイルをエディタのバッファ(タブのようなもの)に貯められるのは便利そうです。興味があれば頑張ってください。

自作コマンド(シェルスクリプト)の設置法

 自作コマンドもCLIツールと言えるので、ここで扱います。(コマンド自体は、#7で作ります)。

 スクリプトファイルは、一つのコマンドに相当します。書いたコマンド(スクリプト)は、(PATHを通せば)どのシェルからでも利用できます。

 つまりbashを書ければ、他のシェルでスクリプトを書けなくても十分です。

~/bin$PATHを通す

 シェルは、コマンドを環境変数$PATHから探します。$PATH~/binを追加すれば、~/binに設置したスクリプトをコマンドとして実行できます。(これを『~binPATHを通す』と表現します)。

 bashにおいて、$PATH:文字区切りのパスの集まりです。このような環境変数は、~/.bash_profileから設定するのが常です。

 export PATH="~/bin:$PATH"~/.bash_profileに追記します。

シェルから追記する

 やや技巧的な書き方をしてみました。普通にエディタで書いて構いません。

$ # パスが通っているかを確認
$ echo "$PATH" | tr ':' '\n' | grep ~/bin || echo not found
not found
$ # ~/binにPATHが通っていなかった場合
$ # 追記されるように .bash_profile を変更する
$ echo 'export PATH="$HOME/bin:$PATH"' | cat - ~/.bash_profile > ~/.bash_profile.new
$ mv ~/.bash_profile{.new,}
$ source $_ # $_ は前回のコマンドの最後の引数
解説
  • tr (translate) は文字の置換を行います
  • grep は行の抽出を行います(マッチがあれば『成功』)
  • cat では - 文字でstdinを表します(そして連結: concatenate してくれました)

 cat file | .. > fileをすると、fileが空になるので気をつけましょう。

ファイルの上書きについて

 teeで出力したり、sed -iで上書きする方法もあります。

 sedは常にGNU系のsedを使うと良いと思います。MacではBSD系のsedが入っていますが、書き方がかなり紛らわしいです。

c.f. GNU sed の用法
  • 1行目に挿入(insert)して上書き: gsed -i '1i text_to_insert' <file>
  • 1行目を消去(delete)して上書き: gsed -i 1d <file>

設定の変更

 書き換えたrcファイルの内容を、現在のシェルに反映します。

予備知識: サブシェルと現在のシェル

 シェルスクリプトは、通常subshell(という名前のサブプロセス)で実行されます。サブシェルで環境変数を変えたり、シェル関数の定義を上書きしても、元のシェルには影響しません。変数なども同様です。

現在のシェルで実行する

 source <file>で、呼び出し元のシェルでファイル内容が実行されます。これまでのrcファイルは、現在のシェルで実行することで、シェルの状態を上書きしてきたのですね。

スクリプトの書き方

 具体的には次回やるので、流してください。

解釈プログラムの宣言

 一行目のshebang (#!/bin/name_of_shell)で表します。

ファイルの末尾で改行

 入れておいたほうが無難です

実行許可 Execure permissions

 作成したファイルは、まだ実行できません。chmod +x <file>で、スクリプトの実行権限を与えます。許可はls -l (もしかしたらllでもok) から確認できます。詳しくは、manを読むか何かの本で。

GNU系のコマンド

 Mac向けです。Macには、初期ではBSD系のコマンドが入っています。GNU系のコマンドも加えましょう。

インストール

 Homebrew経由で入れていきます。gxxxという名前になります。BSD系のコマンドを上書きしたい場合は、こちらの記事などを参照してみたください(Qiita)。

$ echo gawk grep gnu-sed findutils | xargs brew install

GNU系commands

gawk, ggrep

 あまり差が分からないので、入れなくてもいいです。gawkは、組み込み関数の種類が豊富だとか。

gsed

 gsedでは、置換内容に改行\nを使えます。-i --in-place(上書き)の書き方が直感的なため、重宝します。(MacBSDsedは複雑)

gxargs

 -dでdelimiter(区切り文字)を指定できます。改行を区切り文字に使えるのは重宝します。

既存コマンドの代わりになるもの

 着色が綺麗だったり、取り回しの良い道具があります。Rust製のものが多いため、先にRustをインストールしておくと良いでしょう。cargoというパッケージマネジャ経由でインストールできます。

マニュアル

tldr

 すでに何度か紹介していますが、具体例が主な非公式マニュアルです。

ファイル関連

 見出しはGitHubへのリンクになっています。

bat

 catの代わりになるコマンドです。ソースコードを鮮やかに着色して表示します。出力が長ければ、ページャを起動して見せてくれます。

fd

 遥かに便利なfindです。再帰的検索、拡張正規表現(ERE)、着色がデフォルトになっています。

ripgrep (rg)

 再帰、着色、ERE、行番号表示がデフォルトで、出力がファイル毎になっているgrepです。

 出力をページャに流すなら、着色を強制するコマンドを用意してもいいかもしれません:

# .bashrc
rg-c() { command rg --color=always "$@" ; }
再訪: グレッグ様の数を数えよ

 fd, rg, それにgxargsがあれば、グレッグ様の数を数えるのも楽だったのでした。

$ # まず .txt ファイルを抽出(相対パス)
$ fd . "$(fd -t d 嘆きの亡霊)/raw" | rg '\.txt$'

$ # グレッグをファイル毎にカウントする場合
$ fd . "$(fd -t d 嘆きの亡霊)/raw" | rg '\.txt$' | gxargs -d '\n' rg -co グレッグ
小説データ/小説家になろう/n6093en 嘆きの亡霊は引退したい _最弱ハンターは英雄の夢を見る_/raw/10 10 腕試し.txt:3
..

$ # ファイル名とマッチ数を抜き出し
$ ls "$(fd -t d 嘆きの亡霊)/raw" | rg '\.txt$' | gxargs -d '\n' rg -co グレッグ | awk -F '/' '{print $(NF-1) $(NF)}'
10 10 腕試し.txt:3
..

$ # 最後にマッチ数の合計を得る
$ fd . "$(fd -t d 嘆きの亡霊)/raw" | rg '\.txt$' | gxargs -d '\n' rg -co グレッグ | awk -F '/' '{print $(NF)}' | awk -F ':' '{sum+=$(NF)} END {print sum}'
148

 今回は、全話を結合した一時ファイルを作りませんでした。計上するのにawkで頑張っています。

exa

 ls / tree の代わりとなるツールです。両者に似たオプションの形を取っているため、乗り換えが楽です。着色が美しいのも特徴的です。

# .bashrc
e() { command exa -F "$@" ; }
el() { command exa -alF "$@" ; }
# ディレクトリのみ表示(着色付き)
e-d() { command exa -F --color=always "$@" | grep / | column ; }
# ディレクトリのみツリー表示(着色付き)
e-dT() { command exa -FT --color=always "$@" | grep / ; }

 exa -lで、容量や実行権限も見られます。

その他 娯楽用ツールなど

 一応紹介してみます。

コンテンツ周り

cmus

 Vim風キー操作の音楽プレイヤです。キュー機能もあって便利です。

 音楽は、主にアーティストのタグで分けて表示されます。アルバム分けなどもしてくれます。

narou.rb

 小説のダウンロードに使用できます。mobaによる解説はこちら

 より便利に使うための記事を執筆中……。(例えば: 現ディレクトリ位置に関係なく使用する)

youtube-dl

 グレーゾーンな気はしますが、ニコニコやYoutubeダウンローダです。音声のみ(サムネイルつき)のダウンロードもできます。詳しくは検索から。

Editors

Neovim / Spacemacs

 Vim入門#1を参照してください。