[Emacs] Diredのshellコマンドで使える置換文字
EmacsのDiredモードは、shellコマンドが実行できるので重宝しています。
複数のファイルを一度に処理できて、置換文字も使えるので、shellと使い分けがナイスなのです。
で、この置換文字、shellのワイルドカード展開と似たような記法なので、なんとなく雰囲気で使っていましたが、これではいかん!ということで、まじめに調べてみました。
diredモードでのShellコマンドを実行する
まずは基本の話です。
Emacsのdiredモードには、ファイルに対してshellコマンドを実行するための関数が用意されています。
- dired-do-shell-command (ショートカットは
!
) - dired-do-async-shell-command (
&
) # 非同期で実行
例えば、次のようなDiredバッファがあるとします。
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image1.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image2.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image3.jpg
画像ファイルの情報が知りたいので、ImageMagickのidentify
を使いたいとき、任意の行へカーソルを移動し、!
を押せば、次のようなプロンプトが表示されます。
! on image1.jpg:
ここで次のコマンドを入力して実行。
! on image1.jpg: identify
コマンドの末尾にファイル名が追加されて、次のように実行されるはず。
identify image1.jpg
実行結果は、エコーエリアにこんな感じで表示されるはず。
image1.jpg JPEG 1600x1200 1600x1200+0+0 8-bit sRGB 196921B 0.000u 0:00.000
これが基本的な使い方です。さらに複雑なコマンドを組み立てるのに、便利な置換文字について説明します。
置換文字*
はShellコマンドが一回だけ実行
置換文字 *
はファイル名へ展開されるので、複数のファイルを指定できるコマンドで使います。
例えば、2つのファイルをマークしているとき(m
キーでマークできますね)
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image1.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image2.jpg
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image3.jpg
次のコマンドを入力すると(マークのあるものだけ対象なのでカーソル行はどの行でも同じ)。
tar cvf work.tar *
実際はこんなshellコマンドが実行されます。
tar cvf work.tar image1.jpg image3.jpg
置換文字?
はファイル単位でコマンド実行
置換文字 ?
はファイル単位で実行したいコマンドで使います。つまり *
が一度しか実行されないのに対して、 ?
はファイルの数だけコマンドが実行されます。
` ? と
?
がありますが、
? `は前後にスペースが必要な場所で使います。
次のように、2つのjpgファイルを選択した状態で、
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image1.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image2.jpg
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image3.jpg
例えば、pngへ変換するなら、こんなコマンドを入力します。
convert ? -resize 150x150 s-`?`
次のconvertコマンドが2回実行されます。
convert image1.jpg -resize 150x150 s-image1.jpg
convert image3.jpg -resize 150x150 s-image3.jpg
前述したとおり、 ?
には前後にスペースが必要なため、二番目の引数には、`?`
を使いました。
このように、 ?
はファイル単位でしか処理できないshellコマンドを使う場合に使います。
ちなみに、コマンドの実行順は、Diredバッファの表示順にしたがいます。つまり日付順へ変更すれば、shellコマンドはファイルの日付順で実行されます。
置換文字*""
はワイルドカード
次は、ちょっと不思議な*""
です。アスタリスクに続けて、ダブルクォーテーションふたつ入力します。
*""
を使うと、shellコマンドへは*
として渡されるので、いわゆるワイルドカード展開が使えます。
前述と同じく画像ファイルの一覧があるとき、
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image1.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image2.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image3.jpg
次のようなコマンドを実行した場合。
identify *""
ワイルドカード展開をするかプロンプトが表示されるのでYesを選択すれば、コマンドが実行されます。Noなら実行はキャンセルされます。
実行されるコマンドは、Shellでワイルドカードを使うのと同じです。
identify *
Diredバッファで選択されたファイルやカーソルの位置とは関係なく、Shellのワイルドカードを展開した結果になります。
置換文字を指定しない場合は、ファイル単位で実行
最初に書いたとおり、置換文字を使わない場合は、コマンドの末尾にファイル名が補完されます。
このとき、複数のファイルを選択していると、ファイル毎にコマンドが実行されます。
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image1.jpg
-rw-r--r-- 1 foobar staff 196921 2 22 22:25 image2.jpg
* -rw-r--r-- 1 foobar staff 196921 2 22 22:25 image3.jpg
ここでidentify
を実行すれば、コマンドが二回実行されます。
indentify image1.jpg
indentify image3.jpg
次のように、まとめて一度だけの実行になるわけではありません。
indentify image1.jpg image3.jpg
さいごに
Diredモードのshellコマンドで使える置換文字についてみてきました。
このようなDiredでのshellの実行を覚えておくと、次のようなメリットがあります。
- ファイルの一括処理に、Diredのファイル選択が利用できる
- ファイル名を入力する手間が省ける
- 実行結果をそのままEmacsで編集できる
以上、参考にしていただければ幸いです。
更新履歴
- 2019-05-13 コマンドの例を変更。誤記の訂正。