アニメ『ブレイブウィッチーズ』(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コマンドのスクリプトを見てみましたが、このの他にもスクリプトで作られているコマンドがあるのでしょうか。確認してみましょう。 […]