ラベル type の投稿を表示しています。 すべての投稿を表示
ラベル type の投稿を表示しています。 すべての投稿を表示

2015年6月23日火曜日

Posted by mattintosh | File under : , , , , ,
前回、type や declare というコマンドを使いました。これらは bash に含まれる内蔵(組み込み)コマンドです。「内蔵」というからには「外部」もあるのですが、ls や cat など、その他多くのコマンドが外部コマンドです。

内蔵コマンドは enable コマンドや help コマンド、man bash、man bash-builtins で確認することができます。 前回のコマンド検索では type を使いましたが、実際にコマンド検索でよく使われるのは which です。なぜ which ではなく type を使ったかというのは以下のスクリプトを実行してみてください。 このコマンドの結果は以下のようになります。 どちらも unset PATH した後にエラーが出ていますが、エラーの内容が異なります。type の方は「ls コマンドが見つからない」と出ていますが、which の方は「そのようなファイルやディレクトリはない」と出ています。これは which が外部コマンドなので unset PATH すると、コマンド名だけでは呼び出しができず、which を実行ができないからです。前回、type を使ったのはそのためです(which にすらパスが通ってない環境ではあまり意味がありませんが)。

type は引数に指定されたコマンドがシェルのエイリアスや関数であればその内容を表示します(これはオプションによって変わります)が、which は外部コマンドのみを探すという違いもあります。

内蔵コマンドと外部コマンドの特徴

内蔵コマンドと外部コマンドの特徴を以下に挙げます。

内蔵コマンドの特徴

  • 外部コマンドより速い
  • PATH に依存しない
  • bash 独自のコマンドがあるため他のシェルで使えない可能性がある(例:ksh で declare は使えない)
  • バージョンによって実装されていないコマンドやオプションがある(例:readarray などは bash 3.2 では使えない)

外部コマンドの特徴

  • 内蔵コマンドより遅い
  • PATH に依存する(※ファイル名のみで呼び出す場合)
  • バージョンやシェルの種類が異なっても同じ動作が期待できる(オプションの種類など)
内蔵コマンドと外部コマンドの両方にメリット・デメリットがあります。プロジェクトなどのルールで実行シェルが bash と決まっているのであれば内蔵コマンドでもいいと思います(ただ、bash に限定してスクリプトを書くことはほとんどないと思います…)。

速度の違い

以下は内蔵コマンドと外部コマンドの速度を比較するためのスクリプトです。 内蔵コマンドの方は0秒未満で終了していますが、外部コマンドの方は16秒近くかかりました。

オプションの違い

Lesson 2 で echo を作ったスクリプトの話をしましたが、「意図しない結果が出力されている部分がある」と話したのを覚えているでしょうか? すでにおわかりだと思いますが、スクリプト内にコメントとして書いていたものは外部コマンドの方の echo の書式です。内蔵の echo はロングオプション(--help や --version)を受け付けません。help echo と man echo で比較してみてください。
# 内蔵 echo の書式
echo [-neE] [arg ...]

# 外部 echo の書式
echo [SHORT-OPTION]... [STRING]...
echo LONG-OPTION

enable も使ったサンプルを置いておきますのでご自由にお試しください。 which の他に whereis というコマンドもありますのでそちらもチェックしてみてください。

2015年6月22日月曜日

Posted by mattintosh | File under : , , , , ,
今回はコマンドがどのように呼び出されているかというお話です。

皆さんコマンドを実行するときはコマンド名だけを入力していると思います。とりあえず以下のようなスクリプトを作成して実行してみてください。 実行結果は以下のようになります。2回目の bash --version が ./gistfile1.sh: line 6: bash: No such file or directory というエラーになっているのがわかります。 そもそも bash というコマンドはどこにあるのでしょうか?ターミナルで確認してみましょう。(type は bash のビルトインコマンドです) bash は /bin/bash にあるようです。

では、普段よく使う ls や cat も同じように探してみましょう。 これらは /bin/ls と /bin/cat にあるようです。(※環境によっては /usr/bin 以下に格納されていることもあります)

/bin という場所にあるのになぜコマンド名だけで呼び出せるのか?それは PATH 変数のおかげです。PATH 変数というのはコマンドを探すためのもので、:(コロン)で区切られたリストです。

実際にどのようなものか見てみましょう。変数は echo や declare(bash builtin) などで確認することができます。 少し整形します。 フルパスではないコマンドが指定された場合、bash は PATH 変数のリストの最初から順番にコマンドを探していきます(上の場合だと /usr/local/bin)。この仕組みのおかげでいちいちフルパスでコマンドを指定しなくてもコマンドを実行することができるようになっています。逆に言えば PATH 変数に含まれていない場所にあるコマンドはコマンド名だけで呼び出すことができません。

さて、上の PATH 変数の内容ですが、あなたの環境で実行した結果は上のものと同じだったでしょうか?恐らく違う結果だったのではないかと思います。なぜ違うのかというと、環境変数の話も絡んできますので今回は「コマンド名だけで呼び出された外部コマンドは PATH 変数のリストの左から順番に検索される」とだけ覚えておいてください。