zshで究極のオペレーションを

第4回使いこなしポイント 一撃編

通常なら他のツールと組み合わせたり、2~3ステップが必要な処理もzshの多様な展開処理を用いれば一発で結果が得られることが多い。

エイリアス

エイリアスは手軽に設定できすぐに効果が得られる便利な機能である。他のシェルでも使える基本的なエイリアスの他に、zshには以下のエイリアスが用意されている。

  • 接尾辞エイリアス
  • グローバルエイリアス

接尾辞エイリアス

接尾辞(suffix)エイリアスは、ファイルの拡張子とそれを開くアプリケーションプログラムの関連付けとも言える機能で、特定の拡張子を特定のプログラム起動に結び付ける。接尾辞エイリアスは alias -s で登録する。

alias -s pdf=xpdf

とすると、拡張子が ".pdf" のファイルをコマンドラインのコマンド位置で「起動」するとxpdfを起動して開く。

% ls
foo.pdf   hoge.pdf
% foo.pdf
zsh: command not found: foo.pdf    (普通は起動できない)
% ./foo.pdf
zsh: permission denied: ./foo.pdf  (これも起動できない)
% alias -s pdf=xpdf
% foo.pdf
(xpdf foo.pdf が起動される)

グローバルエイリアス

通常のエイリアスはコマンドラインのコマンド位置でのみ展開されるが、グローバルエイリアスは任意の位置で展開される(単語として独立していれば⁠⁠。

% alias foo=yes
% echo foo
foo                (コマンド位置でないのでfooのまま)
% alias -g foo=yes
% echo foo
yes                (展開される)
% unalias foo
unalias: no such hash table element: yes
(fooが先にyesに展開されるので、エイリアスを解除するには以下のようにする)
% unalias \foo
% echo foo
foo

よく参照するファイル名などをグローバルエイリアスに定義しておいても便利だが、リダイレクトのようにコマンド位置に依らず利用できるものを登録しておくとより便利だろう。

% alias -g NL='>/dev/null'
% echo hello NL
("echo hello >/dev/null" に展開されるので何も出力されない)
% echo NL hello
("echo >/dev/null hello" に展開され、これも何も出力されない)
% NL echo hello
(">/dev/null echo hello" に展開され、これも何も出力されない)
% NL chmod
usage: chmod [-R [-H | -L | -P]] [-h] mode file ...
% alias -g NLL='> /dev/null 2>&1'
% NLL chmod
(何も出力されない)

ファイル名処理

zshには、大量に存在するファイルから狙ったものを確実に選び出すための表記法が豊富に用意されている。ここでは実際の操作に即した代表的な例を示しつついくつかの記法を紹介する。

基本オペレータ

多くのシェルで共通して使える記号をまず示しておこう。

*(アスタリスク)
0字以上の任意の長さの名前にマッチする。
?(クェスチョンマーク)
任意の1字。
[]
括弧内に列挙した文字のいずれか1字にマッチ。列挙の代わりに`0-9'や`a-f'のようにハイフンでつないだ文字範囲指定や、[:alnum:]のようなlocaleに応じたシンボリックな文字種指定も利用できる。
[^]
[] の逆転で、^以降に列挙した文字にマッチしない1字にマッチする。

zsh固有のオペレータ

まずシェルオプション extended_globをセット(サンプルzshrc には記述済みしておこう。

setopt extended_glob

これをセットすることで、除外パターン、大文字小文字同一視など、すべての拡張表記が可能となる。それらを以下に示す。

()
グルーピングに用いる。後述の `|' による「または」の意味の及ぶ範囲や、繰り返し指定の適用範囲を限定するために使われる。
<m-n>
ファイル名の該当部分を整数として解釈したとき、それがmからnの範囲にあるものにマッチする。以下の例を参照(下限か上限の片方は省略可能⁠⁠。
% ls
001  01   1    10   100  25   5    8
% echo <1-20>
001 01 1 10 5 8
x|y
パターン x または y のいずれかにマッチする。プロセスをパイプでつなぐときの表記と区別するため、必ず ( ) でグルーピングして用いる。
% ls
bar       bar.o     bar.tex   foo.c     foo.obj
bar.c     bar.obj   foo       foo.o     foo.tex
% ls f*.(c|o|obj|s)
foo.c     foo.o     foo.obj
^x

x というパターンにマッチするもの以外にマッチ。

z~x
z というパターンにマッチするものから、xにマッチするものを除外。
x#
パターン x が0回以上繰り返すものにマッチ。
x##
パターン x が1回以上繰り返すものにマッチ。

最後から2番目の#を利用し(*/)#とすると、""(空)、"*/""*/*/""*/*/*/"… つまり任意段の階層のディレクトリを辿った再帰的なファイルマッチングのためのパターンとなる。これはよく用いるので **/ という簡略表記が用意されている。

また、マッチングの規則を変更する記法も用意されている。

(#i)
(小文字のエル)これより後ろに書いたパターンを大文字小文字を同一視してマッチングを行なう。
(#l)
これより後ろに書いたパターンが小文字で書かれているときのみ、大文字小文字を同一視してマッチングを行なう。

たとえば、/usr/(#i)x11R7/usr/X11R7にも/usr/x11r7いずれにもマッチするが、/usr/(#l)x11R7/usr/X11R7 にはマッチするものの/usr/x11r7にはマッチしない。

ファイル修飾子

上記のオペレータは名前を規準としたファイル選択であるが、ファイルの属性を規準とした選択をすることができる。ファイル名指定の末尾に括弧 ( ) を付け、その内部にファイル修飾子を1つ以上指定する。指定できるファイル修飾子のうち使用頻度が高く有用なものを選んで示す。

修飾子意味
/ディレクトリ
.通常ファイル
@シンボリックリンク
*実行ファイル
x所有者実行ビットの立っているもの
ssetuidビットの立っているもの
uID 所有者UIDがIDのものIDは整数か:ユーザ名:のようにユーザ名を同じ文字で挟んで指定する)
a時刻指定 時刻指定 のアクセス時刻を持つファイル:
時刻指定 には整数 nを書くとn 日前の時刻指定、`M'、`w'、`h'、 `m'、`s' を前置した整数を書くとそれぞれ 月、週、時間、分、秒が単位となる。整数の直前に `+' を付けると「より大きい⁠⁠、整数の直前に `-' を付けると「未満」の意味となる。たとえば、`*(am-20)' とすると `*' にマッチするファイルのうちアクセス時刻が20分未満のものが選ばれる。次の修飾子 mc での時刻指定もこれと同様
m時刻指定 時刻指定の修正時刻を持つファイル
c時刻指定時刻指定 のinode更新時刻を持つファイル
Lサイズ指定 ファイルサイズが サイズ指定 で指定したもの:
サイズ指定 には整数を書くとバイト数の指定、`k'、`m'、`p' を前置した整数を書くとそれぞれ KB、MB、ブロック(512バイト)単位、 整数の直前に `+' を付けると「より大きい⁠⁠、整数の直前に `-' を付けると「未満」の意味となる。たとえば、`*(Lm-20)' とすると `*' にマッチするファイルのうち 20MB 未満のものが選ばれる
-修飾子適用先をシンボリックリンクの指しているファイルとする
^以降に指定した修飾子の意味を反転
Nマッチするファイルがない場合は、空文字列に展開する
Dドットで始まる名前にもマッチさせる
ox
(小文字オー)
o の直後の文字 x に従い、展開後のソート規則を決める:
  • n ファイル名(デフォルト)
  • L ファイルサイズ
  • l リンクカウント
  • a アクセス時刻
  • m 修正時刻
  • c inode更新時刻
  • d ディレクトリ優先
  • N ソート無し
Ox
(大文字オー)
ox と同様だがソート順を逆に
[m] マッチするもののうち m 番目のみ取り出す(最初は1番目)
[m,n] マッチするもののうち m 番目から n 番目のみ取り出す

生成ファイル名の加工

何らかのファイル名のパターン指定が展開され、いくつかのファイル名の集合となるときに、それらをそのまま得るのではなく各ファイル名文字列を各々加工したものを得ることができる。

これにはヒストリ展開のときと同じように、以下の編集子が利用できる。

:h (head)
各ファイル名のディレクトリ名部分のみ取り出す。
:t (tail)
各ファイル名のファイル名部分(最後のスラッシュ以降)のみ取り出す。
:e (extension)
各ファイル名の拡張子部分(最後のピリオドより後ろ)のみ取り出す。
:r (root)
各ファイル名の基幹部分(最後のピリオドより前)のみ取り出す。
:s/OLD/NEW/ (substitute)
各ファイル名の最初に現れる OLDNEW に置換。
:gs/OLD/NEW/ (global s)
各ファイル名のすべての OLDNEW に置換。
:&
直前の置換を繰り返し適用

たとえば *.c(:r) とすると、カレントディレクトリにあるすべての*.c ファイルの拡張子部分を取り除いた名前が得られる。

また、以下のようにするとカレントディレクトリ以下すべてのディレクトリのうち、index.html があるディレクトリのみを選び、そのディレクトリのフルバックアップを tar.gz ファイルに取ることができる。

% tar zcf /tmp/backup.tar.gz **/index.html(:h)

コマンドのフルパス展開

登録されたコマンド検索パスにあるコマンド名の前に `='を付けると、実際に起動されるコマンドのフルパスに展開される。

たとえば、以下のコマンドは、コマンド起動 `ls' によって実際に起動されるプログラムを調べ、仮にそれが /bin/ls だとしたら"/bin/ls"に展開される。

=ls

また、インストールされているコマンドが最新版か確かめたいときなど、以下のようにすると効率的である。

% ls -lF =command

プロセス置換

Unixコマンドは、⁠ファイル名を渡すとそのファイルから読み、渡さない場合は標準入力を読む」という風に設計されているものが多い。しかしながら標準入力は1つしかないので、2つ以上のファイルを同時に処理対象とするコマンドに、フィルタ処理した結果を渡そうとするとテンポラリファイルを作る面倒が発生する。

たとえば、日本語を含む2つのバージョン違いのファイルを diffコマンドで比較したいとする。各ファイルの漢字コードが不揃いなのでEUC-JPに統一してから比較しようとする場合、標準的なシェル作業では以下のような手順が考えられる。

% nkf -e file1 > file1.euc
% nkf -e file2 > file2.euc
% diff -ua file[12].euc | less
% rm file[12].euc

このような場合に、zshのプロセス置換記法の1つを用いると以下のような1文で処理が書ける。

% diff -ua =(nkf -e file1) =(nkf -e file2) | less

zshのプロセス置換には以下の記法がある。

<(CommandLine)
CommandLine を非同期的に起動し、その出力が得られるファイル名/dev/fdや名前つきパイプなど)に置換される。
>(CommandLine)
CommandLine を非同期的に起動し、それへの入力となるファイル名に置換される。
=(CommandLine)
CommandLine からの出力を保存した一時ファイルの名前に置換される。

ブレース展開

ブレース(中括弧; { }は、複数の単語を容易に生成するために利用できる。他のシェルでもたとえば以下のように、前後に置いた単語と、ブレース内にカンマ区切りで列挙した単語を連結した複数の単語に展開できる。

% echo {sta,men,cap}tion
station mention caption
% cp sub/dir/ecto/ry/somefile{,.bak}
(cp sub/dir/ecto/ry/somefile sub/dir/ecto/ry/somefile.bak が実行される)

zshではこれに加え、以下の展開も利用できる。

{m..n}

2つの自然数 m から n までをすべて列挙したもの。

例:
% echo {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
% echo {01..20}
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
% echo {001..20}
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020
% echo {12..3}
12 11 10 9 8 7 6 5 4 3
% echo -{12..3}
-12 -11 -10 -9 -8 -7 -6 -5 -4 -3
{c1-c2}

文字c1 から c2までのすべての文字。シェルオプション brace_ccl が必要。

例:
% setopt braceccl
% echo {0-9A-Ma-z}
0 9 A B C D E F G H I J K L M a b c d e f

まとめ

zshが提供する様々な展開は、シェル上の作業で頻繁に登場する典型的な一連の処理を一発で行なえるような工夫が込められている。その他にも多くの展開処理があるので、ひとつひとつ紐解いてゆくことで作業の高速化が期待できる。

次回は、zshの力を特徴づける補完機能について紹介したい。

おすすめ記事

記事・ニュース一覧