【Ruby2.6】__FILE__ について考える。
前置き
Ruby の擬似変数__FILE__
について、色々考えます。
そもそも、__FILE__
って何?
__FILE__
は、「擬似変数」と呼ばれるものの一種です。Webで公開されているリファレンスマニュアルによると・・・
__FILE__
現在のソースファイル名
フルパスとは限らないため、フルパスが必要な場合はFile.expand_path(__FILE__)
とする必要があります。
となっています。実際、コード上で p __FILE__
で出力してみると、ファイル名のみだったり、フルパスだったり、中途半端に相対パスだったりと、さまざまな値が返ってきます。。。
Windows 環境のRubyで、以下のように確認してみました。
テスト用のファイル「C:\gyobo\test\a.rb」を作ります。内容は以下の一文のみ。
p __FILE__
これを、色々な方法で実行してみました。
C:\gyobo\test> ruby a.rb # => "a.rb" C:\gyobo> ruby test\a.rb # => "test\a.rb" C:\gyobo> ruby C:\gyobo\test\a.rb # => "C:\gyobo\test\a.rb" C:\gyobo> ruby c:\gyobo\test\a.rb # => "c:\gyobo\test\a.rb" あれ? C:\gyobo> ruby ../gyobo\test\..\test\a.rb # => "../gyobo/test/../test/a.rb" そういうこと?
4行目、たまたまドライブ文字を小文字にしてみたら、__FILE__
の中身も小文字になったので、まさか・・・と思って5行目でやんちゃなことをしてみたのですが、、、
結局のところ、ruby コマンドで渡された実行ファイルへのパス、引数に指定したパスの文字列がそのまんま、__FILE__
に入るということのようです。
require
や load
で呼び出した場合
Ruby を実行開始したファイルではなく、require
や load
で呼び出した先では、__FILE__
の値はどうなるか?
先ほどの「a.rb」と同じディレクトリに、「req.rb」というファイルを作り、下の一行だけ書きます。
require './a.rb'
実行すると・・・
C:\gyobo\test>ruby req.rb "C:/gyobo/test/a.rb"
相対パスで指定していますが、__FILE__
には絶対パスが格納されています。これは、require
だけでなく、require_relative
や load
で読み込んでも同じです。また、カレントディレクトリを変更して実行した場合も同様*1。require
で指定する相対パスで探索し、見つかったらその絶対パスが入ってくるようです。
__FILE__
で得られるもの
まとめると、以下の通りのようです。
__FILE__
には、そのファイルを呼び出した際のパス文字列が格納される。
ポイントは、「文字列」である、ということです。
__FILE__.class # => String
ファイル/ディレクトリオブジェクトではないので、格納されている文字列以上の情報は入っていません。上記1 の場合、__FILE__
の中身は相対パスの文字列でしかないので、__FILE__
だけでは、絶対パスを生成することはできません。ですので、絶対パスを取得する場合は、最初の引用の中にある通り、
フルパスとは限らないため、フルパスが必要な場合は
File.expand_path(__FILE__)
とする必要があります。
カレントディレクトリを基準に、絶対パスに展開できる File.expand_path
等を使って生成する必要があるわけです。
続きます。