(1/2)今回のテーマはごく短いシェルスクリプトだ。「このスクリプトにどんな意味があるのだろう」とか、「役に立つのだろうか」と思う方もいるかもしれない。あなたが作成するシェルスクリプトに直接役立つことはないが、今回のテーマは、今後シェルスクリプトのスキルを上げていきたいと願う人なら、絶対に押さえておきたいものだ。});/usr/bin/cdをよく読んでみろ今回は、最初に短いシェルスクリプトを紹介する。このごく短いシェルスクリプトが今回のテーマだ。わけが分からないという人もいるかもしれないが、この部分をしっかり押さえた人と、わけが分からないからと放置した人とでは、後々とてつもなく大きな差が付く。今回のテーマは、シェルスクリプトマスターになるためには、ぜひとも抑えておきたいポイントなのだ。最初は理解できないところが多いかもしれないが、後々必ず役に立つと約束する。読み進めていただきたい。Vim連載の第8回目で作業環境のセットアップについて紹介したが、この話を参考に仮想環境などをセットアップしてあるなら実際に試してみてほしい。XやSolarisなどでも同じようなシェルスクリプトを確認できる。UbuntuやFedora、CentOS、openSUSEなどにはこれから紹介するようなスクリプトは存在しないので、何か別の環境で試してほしい。シェルを使っていればcdコマンドを使わないということはあり得ないと思う。Xでは組み込みコマンドだけでなく、通常のコマンドとして独立したものも存在する。/usr/bin/cdがそれだ。9.0には次のようなスクリプトが存在する。/tmp」のように実行すると、何事もなかったのように処理が終わる。/usr/bin/cdを実行しても、/usr/bin/cdを実行するために使用したシェルに何か影響があるというわけではない。このようなスクリプトが存在しているのか不思議に思うだろう。読みやすくするためにコメントを削除すると次のようになる。151635)、実際に機能を実現しているのは次のコードということになる。${1+"$@"}「${0##*/}」は説明しなくても理解できる方が多いかと思う。${0}でコマンド名が渡される。/tmp」なら「/usr/bin/cd」が入っている。「##*/」で、先頭から始まり、「*/」に最長一致する部分を削除する。その結果、「${0##*/}」では「/usr/bin/cd」が「cd」になる。パスを削除してファイル名やディレクトリ名だけを取り出す方法としてよく使うテクニックだ。「${1+"$@"}」の部分では頭をひねる方が多いと思う。書かなくとも「"$@"」と書けば同じことじゃないかという指摘を受けそうだ。いうのも、「${1+"$@"}」で「+」を記述するのは、値がセットされていないかまたはnullの場合にはnullを、そうでない場合には+の後の値を使うようにするという意味がある。「${1+"$@"}」の指定は、引数が何もなければnullであり、そうでなければ「"$@"」となる。いうことで「"$@"」と同じではないか、というわけだ。実は過去に、これとは違う動作を見せる実装系を持つ環境があった。した環境では引数に何も指定しないと、「"$@"」が「""」を意味していた。引数は存在しないのに、引数は1つあるということになるわけだ。「${1+"$@"}」と記述しておけば、そういった場合も引数は0になる。「${1+"$@"}」は、引数がない場合に「"$@"」が「""」になってしまう環境でもnullとして扱われるように対策を施した結果であるというわけだ。FreeBSDのashでは「${@+"$@"}」としても同じように動作する。「${1+"$@"}」や「${@+"$@"}」と記述しているスクリプトを時々見かけるのは、こうした理由からである。その処理には本当に意味がないのか?つまり/usr/bin/cdは、シェルを起動してその中で組み込みコマンドのcdを実行する、という処理になっている。/tmp」を実行するという処理になる。考えてみると奇妙な話だ。処理としては成立するが、意味がないように見える。${1+"$@"}実行される組み込みコマンドは「${0##*/}」によって決まっているため、仮にコマンド名がcdではなくaliasであったのなら、このスクリプトは組み込みコマンドであるaliasを実行するものになる。このシェルスクリプトはつまり、コマンドとして実行された処理を、シェルを起動して同じ名前の組み込みコマンドを実行する、という処理をしていることになる。汎用性を持たせながら、こうした意味がない処理をするとはなんとも解せない話だ。先ほどのスクリプトは、実際には次のように先頭にbuiltinという組み込みコマンドが入っている。Xのように大文字と小文字を区別しないファイルシステムでは、最初のシンプルなスクリプトでは処理がうまくいかないことがある。builtin組み込みコマンドを指定して明示的に処理しているのはそのためだ。同じ名前のコマンドがいくつもあるのか考えてみろスクリプトの内容から推測できるように、/usr/bin/には/usr/bin/cdと同じコマンドがほかにも存在する。意味がないコマンドを用意することを不可解に思う方は少なくないはずだ。9.0で次のように/usr/bin/cdを調べると、まったく同じファイルがcdを含めて15個も存在することを確認できる。wait%ls(1)コマンドのiオプションはi-node番号を表示させるものだ。i-node番号が同じということは、実体が同じであるということだ。ハードリンクで作成したファイルということになる。実際、これらファイルは単一のファイルに対するリンクである。PC-BSD/FreeBSDなら/usr/src/usr.bin/alias/Makefileにその処理を見ることができる。XやSolarisにも存在している。メールマガジンをご購読ください。申し込みページへITmediaはアイティメディア株式会社の登録商標です。