今更ながらこれが鬱陶しいことに気付く。
本物の Unix ツールを本物の Unix で使う場合はこういうことはあんまり起こらないんだけれど、Windows なんかで「Unix 生まれのツールを、実行形式のみにパスを通して使う」ようないい加減なことを良くやるわけね。アタシの場合は ffmpeg なんぞがまさしくそうで、普段は「動かせりゃいい」ノリで /bin までを環境変数 PATH に追加するだけで満足している。
そうするとな、/bin だけでなく /include なんぞも楽に参照したい場合に毎度面倒くさい:
1 me@host: ~$ type -p ffmpeg
2 /c/Program Files/ffmpeg-20140916-git-b76d613-win64-static/bin/ffmpeg
3 me@host: ~$ dirname "`type -p ffmpeg`"
4 /c/Program Files/ffmpeg-20140916-git-b76d613-win64-static/bin
5 me@host: ~$ dirname "`dirname \"\`type -p ffmpeg\`\"`"
6 /c/Program Files/ffmpeg-20140916-git-b76d613-win64-static
2つ上までならなんとかなるけれど、3つ上指したくなったらと考えると頭痛くなってくる。どうなんだろな、「最新の *utils」とかだと追加のオプションとか出来てたりすんのかな、ただ「MSYS」な(bash builtin の)dirname は一階層しか上がれない。
一応 Unix の「(文字通り bash ですらない素の) bourne shell」スクリプトで書いた:
1 #! /bin/sh
2 PROG="`basename \"$0\"`"
3 USAGE="\
4 ${PROG} [-p count] path"
5
6 GEN=1
7
8 while test $# != 0
9 do
10 case $1 in
11 -p) test $# -lt 2 && { echo "$USAGE" 1>&2; exit 1; }
12 GEN="$2";
13 shift 2 ;;
14 -p*) GEN="`echo $1 | sed s@^..@@`";
15 shift ;;
16 *) break
17 esac
18 done
19
20
21 RES="$1"
22 while test $GEN -ge 1
23 do
24 RES="`dirname \"$RES\"`"
25 GEN=`expr $GEN - 1`
26 done
27 echo $RES
(つーか「dirname」依存なこと自体、暗黙に bash を期待してはいるんだけれど、「builtin でない dirname」もないわけではないしね。)
今度はラクチン:
1 me@host: ~$ dirnamep "`type -p ffmpeg`"
2 /c/Program Files/ffmpeg-20140916-git-b76d613-win64-static/bin
3 me@host: ~$ dirnamep -p2 "`type -p ffmpeg`"
4 /c/Program Files/ffmpeg-20140916-git-b76d613-win64-static
5 me@host: ~$ dirnamep -p3 "`type -p ffmpeg`"
6 /c/Program Files
7 me@host: ~$
なんでシェルスクリプトで書いたかって? 「速度」が理由ではないよ。ただ別に python はお呼びでもないかなと思っただけ。