普段Macを使って作業をしているが、ちょっとしたプログラムを書いてテストするときはよくデスクトップに保存してからターミナルを起動する。chmod +xとして該当のプログラムファイルをドラッグし、実行の属性を与え、もう一度そのファイルをドラッグして実行。
テストプログラムを書く時はこれの繰り返しだ。

だがターミナルを立ち上げた時のカレントディレクトリはホームディレクトリがデフォルトなので例えばデスクトップに保存されているプログラムファイルから外部ファイルをオープンしている場合(このファイルもたいていはデスクトップなので)'No such file or directory'のエラーが出て怒られる事がよくある。
外部ファイルとはプログラム中で"use"や"require"しているファイルの場合もあるしopen関数で読み込みたいファイルをさす場合もある。

もちろんターミナルを起動してすぐに"chdir Desktop"とすれば全然問題ないし読み込むファイル名をフルパスで指定していればまあそれでも問題ない。

ただ、ターミナルの起動中はディレクトリが一定じゃないのはしょっちゅうだしフルパスでファイル名を書いても環境が変わればパスも変わったりするので、プログラムファイルの先頭部分によくディレクトリ移動のコマンドを書いたりする。

Rubyなら次の1行

Dir.chdir File.dirname(ENV["_"])

もしくは

Dir.chdir File.dirname(__FILE__)

Pythonなら

import os
    os.chdir(os.path.dirname(os.environ['_']))

もしくは

import os
    os.chdir(os.path.dirname(__file__))

Perlなら

BEGIN {
    use File::Basename;
    chdir dirname $0;
}

もしくは

BEGIN {
    use File::Basename;
    chdir dirname $ENV{'_'};
}

もしくは

BEGIN {
    use File::Basename;
    chdir dirname __FILE__;
}

こんな感じに。
これでどのディレクトリにいてもプログラムの先頭で必ずプログラムファイルが存在するディレクトリに移動してくれる。
ただ'__FILE__'という変数名(定数名)は厳密には起動したプログラムファイルとは
限らない、例えばimportやuseされているファイル中で

print __FILE__

とするとそちらのファイル名が出力されるからだ。
なので環境変数の方($ENVやENV)を使う方がいいのかも。

ちなみにPerlの場合BEGINブロックで囲っているが、これがないと"use"は使えない"require"は使える。
useはスクリプト全体が実行される前に実行するので

use File::Basename;
chdir dirname __FILE__;
use 読み込みたいファイル;

と、たとえ先に"chdir"を書いてもuseの方が先に実行される為だ。
当然その時は@INCに無いディレクトリからはファイルを読み込む事は出来ない。

カテゴリ:

トラックバック(0)

トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/9

コメントする