「伝わるプレゼンをする方法」という発表をしてきた

3/3に「俺の話を聞け」というイベントがあった。
『俺の話を聞け!2012』を開催します - 頭ん中

何を話してもOKな自由な勉強会のようだ。良い機会なので、勉強会で発表するときのコツ、気をつけることについて自分なりにまとめてみて発表することにした。最近ほとんど勉強会とか出ていなくて久しぶりの発表なので、けっこう緊張しながら会場に向かった。

発表内容

発表のタイトルは「伝わるプレゼンをする方法」。

僕が普段から発表するときに気をつけていること、ということで「ストーリーを付けると良いよ」という内容で話してきた。

スライドには書けなかったこともあるのでちょっと補足する。

  • 前半は誰にでも分かる人目を引く話をして聞き手を引きつけると良い。いわゆる「つかみ」。
  • 「これを聞いてくれ!」「これがすごい!」と気持ちを込めて伝えると盛り上がる
  • 発表中は失敗しても気にしない。失敗してしまったものはどうしようもないし、フォローしようとしてもたいてい逆効果になるだけ。反省会は家に帰ってからやる。
  • 発表資料を作るときは、画面の上下、左右の端まで書かないようにする。スクリーンが切れて見えなくなることがあるから。特に下の方は後ろの人からは見えにくいので注意する。
  • 他の人の発表を見るのが一番参考になる。うまいと思ったところは真似して、良くないと思ったところはそうならないように注意する。

後はスライドの中でも書いたけど、Presentation Patternsというサイトにいい感じの手法がまとまっていている。こういうのを参考にしながら自分なりのやり方を見つけていくのが良いと思う。

でもここに挙げたのは発表の手法であって、そもそも内容が一番大事ということは忘れないようにしよう。

イベント全体について

久しぶりに勉強会に参加して色々刺激になった。やっぱりがんがんアウトプットするのが大事だと思う。発表するのは準備とか大変だしはっきり言って面倒くさいけど、聞いてくれる人がいればこそできることだと思う。主催者の@msngさん、参加者の皆さん、ありがとうございました。

最近あまり目立つ活動をしていなくてちょっと世間の流行から取り残されていたような感じだったので、これをきっかけにいろんなイベントに参加して活動を復活しようと思う。

あと、次は zsh で発表したい。

Node.jsとnvmを初めてインストールするときのハマりポイントと対策

最近何かと話題の Node.js を使ってみることにした。 インストール自体は公式の Wiki を見ればそんなに難しくない。いつもの configure, make, make install するだけだ。

でも Node.js はまだまだ開発中のプロジェクトで、今でもがんがん更新されてる。すぐに新しいバージョンが出てくるんだけど、そのたびにソースからインストールし直すのもいやだし、ちょっと前のバージョンに戻したくなることもあるかもしれない。

そんなわけで、最近の Node.js は nvm というツールを使うのが流行みたいだ。こいつを使うと複数バージョンのインストール、切り替えが出来るようなって便利。

Mac でも Linux(Ubuntu) でも使えるんだけど、微妙にハマったとこがあったので手順を書いておく。

2012/03/21追記

npm でのパッケージのインストール、設定について追記した。

準備

まず始めに、必要なパッケージとかをあらかじめインストールしておく。

Ubuntu の場合

Node.js をビルドできるようにするために、以下をインストールする。

% sudo aptitude install build-essential
% sudo aptitude install libssl-dev

あと、nvm は wgetcurl の両方が必要になる(統一しろよ...)。Ubuntu はデフォルトで curl が入っていないのでインストールしておこう。

% sudo aptitude install curl
Mac の場合

Mac でも基本的に Ubuntu と同じ。まず XCode をインストールして Node.js 自体をビルドできるようにしよう。

Mac の場合、 curl は入ってるんだけど wget が入っていないのでインストールする。

# homebrew を使う場合
% brew install wget

# Mac ports を使う場合
% sudo port install wget

もちろんインストール済みならそのままで OK。この辺は各自の環境に合わせて適当に調整しよう。

nvm のインストール

nvm は Node Version Manager のことで、Node.js のインストール、バージョンごとの管理、シェルの環境設定をやってくれる。

nvm を使うには Github のリポジトリをクローンする。

% git clone git://github.com/creationix/nvm.git ~/.nvm

あとは nvm 本体を source すれば OK。

% source ~/.nvm/nvm.sh
2012/03/20追記

以前は zsh でエラーが出ていたけど、現状の最新バージョンでは修正されてるので以下の対応は不要になった。念のため以前の対応内容も残しておく。

旧バージョンでエラーが出ていたときの対応(現在は不要)

... のはずなんだけど zsh の場合はエラーが出てしまう。実は nvm.sh は bash が前提になっていて、${BASH_ARGV[0]} ってとこが zsh で解釈できないからだ。

この問題は本家の Issues にも挙がってるので、それを参考に bash でも zsh でも動くように直した。

diff --git a/nvm.sh b/nvm.sh
index 99eb87a..9e9951b 100644
--- a/nvm.sh
+++ b/nvm.sh
@@ -5,8 +5,7 @@
 # Implemented by Tim Caswell <tim@creationix.com>
 # with much bash help from Matthew Ranney

-# Auto detect the NVM_DIR using magic bash 3.x stuff
-export NVM_DIR=$(dirname ${BASH_ARGV[0]})
+export NVM_DIR=$(cd $(dirname ${BASH_SOURCE[0]:-$0}); pwd)

 nvm()
 {

これを適応して、改めて source してみよう。

% source ~/.nvm/nvm.sh

エラーが出なくなった。よしよし。

nvm を使用して Node.js をインストールする

いよいよ Node.js 本体をインストールする。nvm がちゃんと入っていればコマンド1つ打つだけでよくて簡単。

今回は 0.4.0 をインストールした。

% nvm install v0.4.0

インストールできたら use コマンドを使って環境を切り替える。

% nvm use v0.4.0
Now using node v0.4.0

ちゃんとインストールできてるか確認してみよう。

% node --version
v0.4.0

OKOK。パスも通ってる。

別のバージョンもインストールできる。試しに0.3系もインストールしてみた。

% nvm install v0.3.8

複数インストールした後は nvm ls コマンドでバージョン一覧が見れる。

% nvm ls
v0.3.8
v0.4.0 *

今有効になってるバージョンには * がつく。別のバージョンに切り替えたいときは use コマンドを使おう。

% nvm use v0.3.8
Now using node v0.3.8

% node --version
v0.3.8

これで複数のバージョンを切り替えできるようになったし、新しいバージョンが出ても簡単に更新できる。

インストールできるバージョン一覧は nvm コマンドでは見れないので、公式のダウンロードページで確認しよう。

npm でモジュールをインストールする

Node.jsでは npm を使って追加のパッケージを管理する。nvm を使うと npm も使えるようになっているので早速試してみる。
バージョンは node v0.6.9, npm 1.1.0-3 で確認した。

# formidable パッケージをインストール
% npm install -g formidable

-g オプションを付けるとグローバルインストールになって、Node.js がインストールされている共通の領域にパッケージがインストールされる。nvm を使用している環境の場合、バージョン別の場所にパッケージがインストールされる形になる。
例えば nvm use v0.6.9 をした後は ~/.nvm/v0.6.9/lib/node_modules の下にインストールされる。

ただし、こうやってインストールしたパッケージを使おうと node を起動しても「見つかりません」というエラーが出てしまう。

これを防ぐために NODE_PATH 環境変数を指定する。node 本体は NODE_PATH からパッケージを探してくれるので、パッケージをインストールしたディレクトリを指定しておけばうまく動く。

# nvm use した後に以下を実行
% export NODE_PATH=${NVM_PATH}_modules

シェルの設定を追加

nvm の設定はログアウトすると無くなってしまうので、シェルの初期化ファイルに書いておこう。

# ~/.zshenv, ~/.bash_profile などに以下を追加
source ~/.nvm/nvm.sh
nvm use "v0.4.0"

ただし、この書き方の場合 nvm とかがインストールされてない環境で余計なエラーが出てしまう。それではかっこわるいのでインストール済みかどうかチェックするようにした。

# nvm と指定されたバージョンの Node.js がインストール済みの場合だけ
# 設定を有効にする
if [[ -f ~/.nvm/nvm.sh ]]; then
  source ~/.nvm/nvm.sh

  if which nvm >/dev/null 2>&1 ;then
    _nodejs_use_version="v0.4.0"
    if nvm ls | grep -F -e "${_nodejs_use_version}" >/dev/null 2>&1 ;then
      nvm use "${_nodejs_use_version}" >/dev/null
      export NODE_PATH=${NVM_PATH}_modules${NODE_PATH:+:}${NODE_PATH}
    fi
    unset _nodejs_use_version
  fi
fi

インストール済みの場合だけ nvm use するようにした。.zshrc をいろんな環境で使い回してるときはこうした方がいいと思う。

これでインストールと環境設定は終わり。新しいバージョンが出てきても簡単に設定を変えれるようになったし、もう安心だ。

15分でわかる zsh

2011年01月29日(土) に大阪で Minami.rb 第4回勉強会 が開かれた(告知ページ)。Ruby on Rails(Ruby)メインの勉強会だ。

そこで15分枠の発表コーナーがあったので zsh の発表をしてきた。zsh って高機能なんだけど、実はシェルに詳しくない人でも便利に使える。なので、なんか興味あるけど難しそうって思ってる人は参考にして欲しい。

発表資料

発表資料はこんな感じ。これ自体はあんまり読まなくてもいいけど、一応貼り付けておく。

これに実際のコマンドライン操作を見せながら説明した。発表内容は以下。

補完

zsh はなんと言っても補完が便利。とにかくこれを ~/.zshrc に書いておこう。

autoload -Uz compinit
compinit

これでいろんなコマンドのオプション、引数をかしこく補完できるようになる。

grep の補完の例

例えば grep の場合。オプションを指定するとき普通はこんな感じになると思う。

% grep -nH -r 'method1' src

でも -n とか -H とか覚えてられない。毎回 --help とか man とかで調べてる人もいるかもしれない。

1文字のオプションは分かりにくいってことで、長いオプションも用意されてる。

% grep --with-filename --line-number --recursive 'method1' src

これはこれでめんどくさい。--with-filename なんて打ってたら日が暮れる。

zsh の補完を使うとこれが全部解決できる。

% grep --wi[TAB]        # ここでタブを押す
% grep --with-filename  # オプション名が補完される
% grep --with-filename --line[TAB]     # 今度もタブを押す
                                       # 候補が出てくる
  --line-buffered        -- flush output on every line
  --line-number          -- prefix output with line numbers
  --line-regexp          -- force pattern to match only whole lines

% grep --with-filename --line-number   # 何回かタブを押して欲しいものを選ぶ

ポイントはオプション名が分からなくてもいいってとこ。何となく名前を入れて、後は補完して選べば OK。オプション名を覚えたり入力したり、そんなどうでもいいことにパワーを使う必要はない。

git の補完の例

みんな大好きな git も当然補完できる

% git a[TAB]     # git コマンドの補完
% git add -[TAB] # add のオプションの補完

% git add [TAB]  # add するファイル名の補完
                 # 編集済みのファイルしか出てこないので、
                 # add する必要のあるファイルだけが補完される

checkout の場合もいい感じに補完してくれる。

% git checkout [TAB] # ファイル名とブランチ名を補完

ブランチを行ったり来たりするときに便利。

その他補完が便利になるもの

その他、補完が便利になるものとしてこんなものがある。

  • man
  • cd
  • kill
  • apt-get

使い方も同じで、何か欲しくなったときにタブを押すだけ。それだけで man の場合はマニュアルページ名を補完してくれるし、 cd の場合はディレクトリ名だけが補完できる。

もちろんこれ以外でも、よく使うコマンドはたいてい対応している。

とにかくこの機能が便利。適当にタブを押すだけでいい感じのものが補完されるので、自分で考えて入力するってのが激減する。

ファイル名生成

補完以外にも、** で指定する再帰的なファイル名生成が便利。

% grep h1 **/*.html

これは grep h1 *.html */*.html */*/*.html ... という意味になるので、今のディレクトリ以下の html ファイル全部が grep 対象になる。

いろいろ使い道がある。

% rm -f **/*.bak  # .bak を削除する
% vim **/*.rb     # ruby ファイルを vim で開く

ファイルを探すのにも使える。

% ls **/MyClass.rb  # ファイル名を指定して探す
% ls **/*.png       # png ファイルを探す

「あのファイルどこいったのかなー」ってときに便利。find コマンドでも同じようなことが出来るんだけど、それよりも簡単に使えてうれしい。

まとめ

なんと言っても zsh は補完が便利。しかも使い方はタブを押すだけ。それだけで zsh がそのとき必要なものを出してくれる。

なので、コマンドラインの操作になれてない人でも便利に使える。というか、コマンドとかオプションとか全部覚えてたら補完する必要はないわけで、あんまりなれてない人にこそ使って欲しい。

zsh は高機能なので難しい設定とかしてる人もいるけど、初心者でも役に立つので自分の扱える範囲で活用して欲しい。

.zshrc の例

簡単な .zshrc の例は以下。とりあえず最初はこのあたりから始めてみよう。

# 強力な補完を有効にする
autoload -Uz compinit
compinit

# ヒストリの設定
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000

# emacs 風キーバインドにする
bindkey -e

# その他とりあえずいるもの
export LANG=ja_JP.UTF-8
setopt print_eight_bit   # 日本語ファイル名を表示可能にする
setopt no_flow_control   # フローコントロールを無効にする

参考資料

漢のzsh | マイコミジャーナル
マイコミジャーナルの連載記事。ちょっと古いけど今読んでも役に立つし、 zsh の一通りのことが解説してある。
連載:zshで究極のオペレーションを|gihyo.jp … 技術評論社
zsh の本の著者による連載記事。
zsh 記事一覧 - ess sup
僕のブログの zsh 記事一覧。
.zshrc - GitHub
僕の .zshrc ファイル。GitHub で公開してる。

Kanasan.JS JavaScript第5版読書会でベジエ曲線について発表した

2011年01月15日(土) に京都で Kanasan.JS JavaScript第5版読書会 #11 が開かれた(告知ページ)。みんなでサイ本を読む会だ。第1回からだいたい3年ぐらい続いてて、今回でいよいよ最終回となった。僕は途中半分の第6回くらいからの参加なんだけど、最後のまとめとして気合いを入れて参加した。

読んだところ

今回は P561 から P629(最後)まで。主にクライアントサイドのグラフィック制御のところを読んだ。

いろんなグラフィック関係のテクニックが書いてあったけど、本が出てから時間がたってることもあって今では使わないようなものもあった。その中で注目はやっぱり SVGcanvas 要素。サンプルコードが書いてあったのでみんなで読んだ。

SVG

SVGXML で定義された画像フォーマットの一種。V は Vector の V で、その名の通りベクターグラフィックになってる。HTML の中に SVG を埋め込めて、さらにそいつを JavaScript から操作できる。

指定した経路に沿って線を書くこともできる。例えば扇形を書くときはこんな風に経路を指定する。

// この文字列に線の経路情報を保持する
var d = "M " + cx + "," + cy +    // 始点(円の中心)
        " L " + x1 + "," + y1 +   // 始点から (x1, y1)まで直線を引く
        " A " + r + "," + r +     // 円弧の半径
        " O " + big + " 1 " +     // 円弧の向き。
                                  // 終端まで弧を書く際に近いほう/遠いほうのどちらを通るかを指定する
        x2 + "," + y2 +           // 円弧の終端
        " Z";                     // 始点まで戻って終わり

超読みにくい。でもこんな指定を繰り返すと円グラフが描けたりする。

canvas 要素

canvas 要素は JavaScript で動的に画像を描くための要素。できあがりはビットマップ画像になる。lineTo, arc などの API を使ってチマチマ画像を描いていく。その後僕は発表したんだけど、そこでも canvas を使った。

ベジエ曲線について

今回はグラフィック関連の章ということで、僕はベジエ曲線について発表した。

ベジエ曲線って名前は聞いたことある、もしくは使ったことあるっていう人も多いんじゃないのかな。 Illustrator, Photoshop とかでも描けるし、canvas 要素の quadraticCurveTo(2次)、bezierCurveTo(3次)という API でも描ける。

でもアルゴリズムまでは知ってる人少ないと思う。僕は学校でそういうの勉強したので、いい機会だと思って発表した。

ベジエ曲線とは

ベジエ曲線とは、線分の内分点を取る操作を繰り返すことにより得られる曲線のこと。といってもよく意味が分からないかもしれない。jsdo.it でデモページを作ったので適当に遊んで欲しい。

入力となるいくつかの点があって、そこからアルゴリズムに基づいて曲線を描く。その「いくつかの点」というのを制御点という。Illustrator では「開始地点のアンカーポイント」とか呼ばれてるやつね。

数学的な理論の話は「ベジエ曲線とベジエ曲面」というページに書いてある。大学の講義用の資料でかなり本格的。その中で、曲線の定義、表現方法は「ベジエ曲線とベジエ曲面1」と「ベジエ曲線とベジエ曲面2」を読むと分かる(どっちも PDF ファイル)。

JavaScript での実装

僕のデモページで一番大事な関数は以下。ベジエ曲線上の1点を求めてる。

// bezierCurve.js 58行目

// 与えられた制御点に対して、 t を固定して得られる
// ベジエ曲線上の1つの点を取得する
// @points : 任意の数の制御点を格納した配列
bezierPointT : function(t, points) {
    if (points.length >= 2) {
        var dividedPoints = [];
        for (var i = 0; i < points.length - 1; i++) {
            dividedPoints.push(
                BezierCurve.dividePoint(t, points[i], points[i+1]));
        }
        return BezierCurve.bezierPointT(t, dividedPoints);
    } else {
        return points[0];
    }
}

この t を0から1まで動かせばなめらかな曲線になる。実際には連続的に無限の点を求めることはできないので、0から1までを適当に分割して折れ線で近似してる。

拡大/縮小、平行移動

ベジエ曲線の便利な性質として「アフィン写像に対して普遍」というのがある。なんかまた難しい用語が出てきたけど、かみ砕いて言うと以下の通り。

  • ベジエ曲線を描いてから曲線全体を平行移動させるのと、先に制御点を平行移動してからベジエ曲線を描くのとでできる結果は同じ
  • 回転、拡大、縮小、鏡写しについても同様
  • そういう変換の組み合わせでも同様

この性質については、さっきの講義ページでは「ベジエ曲線とベジエ曲面6」に解説がある(これも PDF)。

実際に曲線を変換する場合は後者の方法、先に制御点を変換する方が楽に実装できる。

さらに、拡大の場合なんかは曲線全体を拡大すると困ることがある。曲線とは言っても実際には折れ線で近似していることを思い出そう。小さいうちは折れ線には見えなくても、拡大すると角の部分も拡大されるのでカクカクに見えてしまう。

そんな場合でも、後者の方法の場合は拡大した分だけ分割数を増やせば角は見えなくなる。曲線のアルゴリズムだけ決まっていて実際の精度は描画する時に決めれるので、必要に応じて精度を上げるということができるのだ。これが「ベクター画像は拡大してもギザギザがでてこない」という理由になってる。ベジエ曲線便利。

実用上はこういう理論を知らなくても必要なところだけ利用すればいいんだけど、数学を使うと「その性質が必ず成り立つ。絶対に大丈夫」という保証ができる。数学って何してるのかいまいち分かりにくいところがあるけど、こんなところに役に立ってる例があった。

あと、最初に言ったように canvas にはベジエ曲線を描く API があるので、これに実用上の意味はない。アルゴリズムを理解するためのサンプル。

そんなこんなで読書会は無事最後まで終了した。

最後に

思い出してみると、僕が初めて参加した勉強会が Kanasan.JS だった。それから2年以上たって、僕のプログラミングのレベルも上がったし、いろいろ発表するようにもなった。この勉強会を通して学んだことは大きかった。

Kanasan.JS はいろんな勉強会の中でもトップクラスの技術レベルだと思う。それもみんなで本を読んだりして勉強した結果だ。メンバーが入れ替わりながら何年も継続できているのは、この勉強会を大切に感じている人がいるからこそだと思う。そして、そういう流れを作ってくれた初代代表の Kanasan にはとても感謝しています。

今回でサイ本読書会が終わったので、次回以降は jQuery コードリーディングと単発企画ものを行う。これからも継続して、関西を代表する勉強会になればいいと思う。

第2回関西アンカンファレンスで zsh の記号プログラミングについて発表した

2010年1月8日に神戸で第2回関西アンカンファレンスが開催された(告知ページ)。僕は zsh が大好きなので「zsh で記号プログラミング」というタイトルで発表した。

発表内容

内容は zshHello world をアルファベット、数字を使わずに記号だけで書くというもの。資料は slidesahre で公開してる

動画もとってもらった。
http://youtube.com/watch?v=BBLFVkTCq6Q
動画の撮影、編集をしてくれた @ さん、ありがとうございました。

ソースコード

ソースコードはこんな感じ。

:
__=$?
((___=!__))
((____=___+___))
((_____=____+___))
((______=_____+___))
((_______=______+___))
((________=____*_____))
((_________=________+___))
((__________=____*______))
((___________=_____*_____))
____________=$(% |& >& $___)
$____________[-$______]$____________[-$____$____]$____________[-$_______]$____________[-$___$_________] "\\$__$___$___$__\\$__$___$______$_______\\$__$___$_______$______\\$__$___$_______$______\\$__$___$_______$_________, \\$__$___$________$_________\\$__$___$_______$_________\\$__$___$________$____\\$__$___$_______$______\\$__$___$______$______!"

こいつを実行すると ...

% zsh hello.zsh
Hello, world!

無事 Hello world が出力された。

コメントを入れて読みやすくするとこんな感じ。

# 0から9までの数字を作る
:
__=$?                       # 0
((___=!__))                 # 1
((____=___+___))            # 2
((_____=____+___))          # 3
((______=_____+___))        # 4
((_______=______+___))      # 5
((________=____*_____))     # 6
((_________=________+___))  # 7
((__________=____*______))  # 8
((___________=_____*_____)) # 9


# 以下のエラーメッセージを変数に代入する
#   kigou.zsh:fg:1: no job control in this shell.
____________=$(% |& >& $___)
# 省略せずに書くと以下の通り
# ____________=$(% 2>&1 | cat >& 1)

# 末尾から 4, 22, 5, 17 文字目をつなげると echo になる
# $____________[-4]$____________[-22]$____________[-5]$____________[-17]

# "Hello, world!" の文字列は
# \0NNN 形式の8進数 ascii コードで表現する
# echo "\\0110\\0145\\0154\\0154\\0157, \\0167\\0157\\0162\\0154\\0144!"
# , スペース ! は記号なのでそのまま書く

# 数字を $__ など最初に作った変数に置き換える
$____________[-$______]$____________[-$____$____]$____________[-$_______]$____________[-$___$_________] "\\$__$___$___$__\\$__$___$______$_______\\$__$___$_______$______\\$__$___$_______$______\\$__$___$_______$_________, \\$__$___$________$_________\\$__$___$_______$_________\\$__$___$________$____\\$__$___$_______$______\\$__$___$______$______!"

zsh らしいスクリプトになったと思う。

感想

僕以外の発表一覧は 第2回関西アンカンファレンス セッション一覧 にまとめられてる。

おもしろい発表がいっぱいあったけど、特によかったのは以下。

非デザイナーがデザイナーっぽい思考をするためのツボ
デザインの話大好き
Googleで始めた風評調査
生々しい
Gmailはショートカットでサクサク使おう
快適そう
美味しそうな写真の撮り方
おいしそう

JavaScript とかのプログラミングの話ももちろんいいんだけど、デザインとか写真とか他の勉強会ではなかなかない話が聞けるところがアンカンファレンスの魅力だと思ってる。

僕も好き勝手に話できるので発表するのを楽しんでます。

最後に

今回の関西アンカンファレンスはいろんな人の協力のもと成り立ってる。

  • 会場を提供してくれた兵庫県立大学神戸キャンパスの皆様
  • 僕のマシントラブルの際に Mac を貸してくれた @msng さん
  • スタッフの皆様
  • 発表してくれた皆様
  • 参加者の皆様
  • 今回の発表のきっかけを作ってくれた 記号プログラミング Advent Calendar の皆様

楽しいイベントになりました。ありがとうございました。

zsh の戦闘力を計測する

vim 使いには戦闘力という概念があって、vimrc の行数で強さを比べる。

せっかくなので zsh でもまねしてみた。

function scouter() {
  sed -e '/^\s*$/d' -e '/^\s*#/d' ${ZDOTDIR:-$HOME}/.zshrc | wc -l
}

zshrc の行数を計れる。.zshrc に書いて実行してみよう。

% scouter
263

もっと強くなりたい。

zsh の zmv を使って簡単に複数ファイルを一括リネームする

連番のファイルがずらーっとあったとき、複数のファイル名を一気にスマートに変えたいことがある。一個ずつちまちまリネームなんてやってられない。そんなときは zsh の zmv を使うと便利なので紹介する。

zmv で何ができるか

例えばこんな感じで 1.txt から 6.txt までファイルがあったとする。

% ls
1.txt 3.txt 5.txt
2.txt 4.txt 6.txt

でも、ファイル名短すぎてわかりにくいなー、file-1.txt みたいに頭に file ってつけたいなー、って思ったとしよう。

そんなときのために zsh には zmv ってコマンドがあって、この手の一括リネームがスマートにできる。お手軽な使い方はこんな感じ。

あらかじめ ~/.zshrc にこう書いておいてから、

autoload -Uz zmv
alias zmv='noglob zmv -W'

一回のコマンドで複数ファイルをリネームできる。

% zmv *.txt file-*.txt

実行してみると ...

% ls
file-1.txt file-3.txt file-5.txt
file-2.txt file-4.txt file-6.txt

1.txt が file-1.txt, 2.txt が file-2.txt ... という風にリネームできた。便利。

使い方の解説

もうちょっと詳しく解説してみる。

オプションなしの使い方

さっきは alias でいろいろオプションつけてたんだけど、まずはオプションなしの場合で説明する。

% zmv '(*).txt' 'file-$1.txt'

これが一番基本的な使い方。左側(第一引数)のパターンにマッチしたファイルを右側(第二引数)のフォーマットで作った名前に mv できる。

カッコの指定と $1 ってのがポイントで、リネームするときに右側の $1 の部分は左側のカッコで囲んだ部分に置き換えられる。カッコの中にワイルドカードを入れておくと実際にマッチした部分が $1 として使われるので、元のファイル名の一部を使ってそれぞれの mv 先のファイル名が作れる。

例えば 005.txt ってファイルは 005 の部分が * にマッチするので $1 が 005 に置き換わって、結果として file-005.txt に mv される。

さらに $1 っていうぐらいなので、$2, $3 ... といくらでも続けれる。例えばこんなの。

% zmv 'hoge-(*).(*).(*).tar.gz' 'hoge-$1--$2--$3.tar.gz'

先に出てきたカッコから順に $1, $2, $3 と対応するので、この場合、hoge-1.2.3.tar.gz が hoge-1--2--3.tar.gz、hoge-2.10.8.tar.gz が hoge-2--10--8.tar.gz にリネームされる。

-w オプション

でもなんかカッコで囲むのめんどくさいな、って思った人もいるかもしれない。僕もそう思う。そんな人のために zmv には -w というオプションがある。

-w オプションをつけると左側のワイルドカード部分を勝手にカッコで囲んだものとして扱ってくれる。なので、さっきの tar.gz の例で言うと全部カッコを省略して書ける。

% zmv -w 'hoge-*.*.*.tar.gz' 'hoge-$1--$2--$3.tar.gz'
-W オプション

こうなってくると人間横着になるもので、右側の $1 ってのもめんどくさくなってくる。せっかく zmv を使うんだから極限まで楽をしたい。zmv を作った人もそう考えたのか、 -W というオプションを作ってくれた(大文字の W ね)。

-W オプションを使うと、 -w (小文字)に加えて右側の * も順番に $1, $2 ... と置き換えてくれる。なので最終的にはこれで OK。

% zmv -W 'hoge-*.*.*.tar.gz' 'hoge-*--*--*.tar.gz'

シンプル。

でも zmv '(*)-(*).txt' '$2-$1.txt' みたいに順番を入れ替えたい場合には使えない。そういうときは -W オプションなしでやろう。

noglob

さっきから引数を '...' で囲んでるけど、これは * をファイル名展開せずに zmv に渡すため。'...' で囲まなかった場合は zsh 自体が zmv に引数を渡す前に * を展開してしまうのでうまく動かない。zmv を使うときはこのファイル名展開は必要ないので無効にしておくといい。

% noglob zmv -W hoge-*.*.*.tar.gz hoge-*--*--*.tar.gz

こんな風に先頭に noglob を付けると zsh が * とかのワイルドカードを展開しなくなるので '...' で囲まなくてもよくなる。

便利な alias

最後の noglob を付けたパターンが典型的な使い方になるので、こんな風に ~/.zshrc に書いておくと便利。

autoload -Uz zmv
alias zmv='noglob zmv -W'

これで Windows のコマンドプロンプトみたいなのができるようになる。

% zmv *.txt *.c

進んだ使い方

ここまでが基本編。ここからもっと凝った使い方を紹介するので何かの時に使ってみよう。

ここから先はさっき紹介した alias とかの設定は無いものとして説明する。

確認する

-n オプションを使うと、実際にリネームせずに行おうとしてるコマンドの内容を出力してくれる。

% zmv -n -W '*.txt' '*.c'
mv -- file1.txt file1.c
mv -- file2.txt file2.c

難しいことやる前には一回これで確認しておくと安全。

-C, -L オプション

-C オプションを付けると mv の代わりに cp を実行するようになる。

# *.c ファイルを *.c.bak にコピーしてバックアップをとる
% zmv -C '(*.c)' '$1.bak'

-L オプションを付けると mv の代わりに ln を実行するようになる。

例えば、~/dotfiles ディレクトリの下に dot.zshrc, dot.vimrc とか dot.* という形式で設定ファイルを置いていたとしよう。ホームディレクトリに .zshrc とか本来の名前でリンクを作る場合はこう。

% cd  # ホームへ移動
% zmv -L -s 'dotfiles/dot.(*)' '.$1'

頭の dot を外してリンクが張れる。

% ls -al
.vimrc -> dotfiles/dot.vimrc
.zshrc -> dotfiles/dot.zshrc

-L を指定した場合はデフォルトでハードリンクが張られるんだけど、 -s を付けるとシンボリックリンクになる。普通は -s を付けておいた方がいいだろう。

あと、-M オプションを付けるとデフォルト動作に戻って mv コマンドを実行するようになる。

変数展開フラグ

右側のリネーム先ファイル名の部分で '${(U)1}.txt' みたいな感じで変数展開フラグが使える。といってもよく意味が分からないかもしれないので例を見てもらおう。

# *.txt の * 部分を大文字にしたい
% ls
readme.txt  todo.txt

# U フラグを使うと ...
% zmv '(*).txt' '${(U)1}.txt'

# カッコで囲んだところが大文字になった
% ls
README.txt  TODO.txt

# 小文字にしたいときは L フラグを使う
% zmv '(*).txt' '${(L)1}.txt'

# 戻った
% ls
readme.txt  todo.txt

変数展開フラグはいっぱいあるんだけど、便利なものは以下。

U
大文字にする(Upper)
L
小文字にする(Lower)
C
キャピタルケース。つまり readme を Readme にする

その他もっとマニアックなことがやりたい人は man zshexpn の Parameter Expansion Flags を参照。

変数名の置換

右側のリネーム先ファイル名の部分で、元の名前を置換できる。これも例を見た方がわかりやすい。

# なんかファイル名にスペースが入ってる。なんとかしたい
% ls -1
hoge 1 x.txt
hoge 2 y.txt

# ${1//pattern/repl} という形式で ...
% zmv '(*)' '${1// /_}'

# スペースが _ に置き換わった
% ls
hoge_1_x.txt  hoge_2_y.txt

ちなみに、スペースがいっぱいあるときは ## が便利。

# 誰だよ、こんなファイル作ったのは ...
% ls -1
hoge    1   x.txt
hoge   2     y.txt

# 直してやるか
% zmv '(*)' '${1// ##/_}'

% ls -1
hoge_1_x.txt
hoge_2_y.txt
# よしよし

## は1回以上の繰り返しを表すので、この場合は連続したスペースが1つの _ になる。

ディレクトリを降りて再帰的に変換する

zsher にはおなじみの **/* も使える。例えば今いるディレクトリ以下にある makefile を全部 Makefile にするのはこんな感じ。

% zmv '(**/)makefile' '$1Makefile'

今いるディレクトリ直下だけでなく、src/project1/makefile とか奥深くにあるファイルもリネームできる。

参考資料

その他参考になる資料一覧を挙げておく。さらに進んだ使い方をするときに読むといいだろう。

zmv の man

何はともあれ zsh の man を見るのがいい。zmv は man zshcontrib に書いてある(だいぶ下の方)。

zsh の man は Web でも読める。
man zshcontrib の OTHER FUNCTIONS

zsh-lovers

zsh-lovers をインストールすると man zsh-lovers で zsh の使い方、Tips とかが読めるようになる。その中に ZMV-Examples ってのがあって、zmv の例がいっぱい書いてある。

こいつも Web で読める。
ZSH-LOVERS(1) - ZMV-Examples

ソースコード

あと、zmv のソースコードの最初の方にコメントで詳しい説明が書いてあるので参考になる。僕の環境(Ubuntu 10.10)では /usr/share/zsh/functions/Misc/zmv にインストールされてた。

ソースは sourceforge にもある。
SourceForge - zsh/zsh/blob - Functions/Misc/zmv

その他の man

変数展開、グロブ展開なんかの zsh 自体の機能が分かってくると色々凝ったリネームができるようになる。参考になる man は以下。

man zshexpn の FILENAME GENERATION
*, x## とかファイル名生成全般についての説明
man zshexpn の Globbing Flags
(*).(#i)jpg の #i とかファイル名生成のフラグについての説明 (#i は大文字小文字を無視するフラグ)
man zshexpn の Parameter Expansion
${1// /_} など $1, $2 ... を置換する方法
man zshexpn の Parameter Expansion Flags
${(U)1} (大文字にする) など

色々やり過ぎると「結局手で一個ずつ直した方が早かった」なんてことになるかもしれないけど、便利なときもあるのでうまく使おう。