アニメ『ブレイブウィッチーズ』(2016)
なんだか『ストライクウィッチーズ』に似てるなあ、似せたものを作るのって難しいのでは、と思っていたら、どうも『ストライクウィッチーズ』の新作のようです。タイトルが違うだけした。『ストライクウィッチーズ』では、501でしたが、今回は、第502統合戦闘航空団です。このアニメシリーズのウィッチは、魔法を使うときに、動物の耳としっぽが生えます。重要な人には重要なポイントなのでしょうね。
今回はウィッチ繋がりで、whichコマンドのソースでも読んでみましょう。
パッケージは、たぶんcoreutilsでしょうか。ソースを取得します。ソースは今後すぐに参照できるように決まったディレクトリ、/usr/srcの下に入れておきます。シンボリックリンクも貼っておきます。
~$ su - # cd /usr/src # apt-get source coreutils (省略) # ln -s coreutils-8.23 coreutils # exit
findでwhichを探してみましょう。
~$ find -L /usr/src/coreutils -name '*which*'
あれ、ありません。ではちゃんと探してみましょう。まずは、which自体をwhichして、パスを得ます。
~$ which which /usr/bin/which ~$
次にパッケージの検索です。
~$ apt-file search /usr/bin/which debian-goodies: /usr/bin/which-pkg-broke debianutils: /usr/bin/which emboss: /usr/bin/whichdb whichman: /usr/bin/whichman ~$
どうやらwhichが格納されているのは、debianutilsのようです。
debianutilsのソースを取得します。例によって、/usr/src/の下に格納してシンボリックリンクを貼っておきます。
~$ su - # cd /usr/src # apt-get source debianutils (省略) # ln -s debianutils-4.4 debianutils # exit
findでwhichのソースを探します。
~$ find -L /usr/src/debianutils -name '*which*' /usr/src/debianutils/po4a/pl/which.1 /usr/src/debianutils/po4a/ja/which.1 /usr/src/debianutils/po4a/de/which.1 /usr/src/debianutils/po4a/it/which.1 /usr/src/debianutils/po4a/es/which.1 /usr/src/debianutils/po4a/sl/which.1 /usr/src/debianutils/po4a/fr/which.1.fr.add /usr/src/debianutils/po4a/fr/which.1 /usr/src/debianutils/which /usr/src/debianutils/which.1 ~$
あれれ、おかしいです。C言語のソースが見当たりません。
もしかして、whichがソースなのでしょうか。fileコマンドでチェックします。
~$ !! | xargs file find -L /usr/src/debianutils -name '*which*' | xargs file /usr/src/debianutils/po4a/pl/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/ja/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/de/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/it/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/es/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/sl/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/fr/which.1.fr.add: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/po4a/fr/which.1: troff or preprocessor input, UTF-8 Unicode text /usr/src/debianutils/which: POSIX shell script, ASCII text executable /usr/src/debianutils/which.1: troff or preprocessor input, ASCII text ~$
下から2行目を見てみると、shell scriptのようです。もしかして、/usr/bin/whichもテキストファイルなのでしょうか。確認してみます。
~$ file /usr/bin/which /usr/bin/which: symbolic link to /bin/which ~$ file /bin/which /bin/which: POSIX shell script, ASCII text executable ~$
やはり同じくテキストファイルでした。headしてみます。wcで行数もみてみましょう。
~$ head /bin/which #! /bin/sh set -ef if test -n "$KSH_VERSION"; then puts() { print -r -- "$*" } else puts() { printf '%s\n' "$*" ~$ wc -l !$ wc -l /bin/which 63 /bin/which ~$
行数も少なく、headを見る限り簡潔に書かれているようですので、この際全文見てみましょう。
~$ cat -n /bin/which 1 #! /bin/sh 2 set -ef 3 4 if test -n "$KSH_VERSION"; then 5 puts() { 6 print -r -- "$*" 7 } 8 else 9 puts() { 10 printf '%s\n' "$*" 11 } 12 fi 13 14 ALLMATCHES=0 15 16 while getopts a whichopts 17 do 18 case "$whichopts" in 19 a) ALLMATCHES=1 ;; 20 ?) puts "Usage: $0 [-a] args"; exit 2 ;; 21 esac 22 done 23 shift $(($OPTIND - 1)) 24 25 if [ "$#" -eq 0 ]; then 26 ALLRET=1 27 else 28 ALLRET=0 29 fi 30 case $PATH in 31 (*[!:]:) PATH="$PATH:" ;; 32 esac 33 for PROGRAM in "$@"; do 34 RET=1 35 IFS_SAVE="$IFS" 36 IFS=: 37 case $PROGRAM in 38 */*) 39 if [ -f "$PROGRAM" ] && [ -x "$PROGRAM" ]; then 40 puts "$PROGRAM" 41 RET=0 42 fi 43 ;; 44 *) 45 for ELEMENT in $PATH; do 46 if [ -z "$ELEMENT" ]; then 47 ELEMENT=. 48 fi 49 if [ -f "$ELEMENT/$PROGRAM" ] && [ -x "$ELEMENT/$PROGRAM" ]; then 50 puts "$ELEMENT/$PROGRAM" 51 RET=0 52 [ "$ALLMATCHES" -eq 1 ] || break 53 fi 54 done 55 ;; 56 esac 57 IFS="$IFS_SAVE" 58 if [ "$RET" -ne 0 ]; then 59 ALLRET=1 60 fi 61 done 62 63 exit "$ALLRET"
このスクリプトには、ライセンス表記がないんですねえ。
PATH中のディレクトリの中に、引数で指定したコマンドのファイルが見つかるかチェックするスクリプトとなっています。PATHは、ご存じのとおり:(コロン)で区切りますが、36行目で、IFSを:(コロン)に設定して、デリミタを:(コロン)とし、ELEMENTにPATH中の各ディレクトリを格納して、
「ELEMENT/引数で指定したコマンド」
のパスのファイルがtestコマンド([])で見つかるかチェックしています。チェックが済んだら、IFSをIFS_SAVEに保存した値で元に戻していますね。
端折って書くとこんな感じになるのでしょうか。作ってみました。
~$ cat -n mywhich.sh 1 for i in `tr : ' ' <<< $PATH`;do 2 if [ -f $i/$1 ];then 3 echo $i/$1 4 fi 5 done ~$
使ってみます。
~$ chmod 755 mywhich.sh ~$ ./mywhich.sh which /usr/bin/which /bin/which
シンボリックリンクと実体のパスが表示されましたね。
whichコマンドと表示を比べてみましょう。
~$ which which /usr/bin/which ~$
なるほど、本物のwhichコマンドは、シンボリックリンクを辿らないようです。
なかなか似せたものを作るのは難しいですね。
コメント
[…] 「whichコマンドの実体」ではwhichコマンドのスクリプトを見てみましたが、このの他にもスクリプトで作られているコマンドがあるのでしょうか。確認してみましょう。 […]