1. ホーム
  2. ruby

[解決済み] Ruby の使用法プロンプトで呼び出されるコマンドの名前を取得するにはどうすればよいですか?

2023-06-20 12:14:45

質問

私はしばらく前に小さなRubyスクリプトを書き、それがかなり気に入っています。私は、適切な数の引数をチェックすることによって、その堅牢性を向上させたいと考えています。

if ARGV.length != 2 then
  puts "Usage: <command> arg1 arg2"
end

もちろん、これは疑似コードだ。とにかく、CやC++では、私は argv[0] のように呼び出したかどうかに関わらず、ユーザが私のコマンドに辿り着くために使った名前を取得することができます。 ./myScript.rb と呼んだか myScript.rb または /usr/local/bin/myScript.rb . Rubyの場合、私は ARGV[0] が最初の真の引数であり ARGV にはコマンド名が含まれていません。これを取得する方法はありますか?

どのように解決するのですか?

Rubyには、呼び出されたスクリプトの名前を伝える方法が3つあります。

#!/usr/bin/env ruby

puts "$0            : #{$0}"
puts "__FILE__      : #{__FILE__}"
puts "$PROGRAM_NAME : #{$PROGRAM_NAME}"

このコードを "test.rb" として保存し、いくつかの方法で呼び出すと、スクリプトが OS から渡された名前を受け取っていることがわかります。スクリプトはOSから渡されたものしか知らないのです。

$ ./test.rb 
$0            : ./test.rb
__FILE__      : ./test.rb
$PROGRAM_NAME : ./test.rb

$ ~/Desktop/test.rb 
$0            : /Users/ttm/Desktop/test.rb
__FILE__      : /Users/ttm/Desktop/test.rb
$PROGRAM_NAME : /Users/ttm/Desktop/test.rb

$ /Users/ttm/Desktop/test.rb 
$0            : /Users/ttm/Desktop/test.rb
__FILE__      : /Users/ttm/Desktop/test.rb
$PROGRAM_NAME : /Users/ttm/Desktop/test.rb

を使って呼び出すと ~ のショートカットを使って呼び出すと、OS はそれを展開されたパスに置き換えて、3番目の例にあるものと一致することを示しています。すべてのケースで、OSが渡したものです。

ハード リンクとソフト リンクの両方を使用してファイルにリンクすると、一貫した動作が示されます。私は test1.rb のハード リンクと test2.rb のソフト リンクを作成しました。

$ ./test1.rb 
$0            : ./test1.rb
__FILE__      : ./test1.rb
$PROGRAM_NAME : ./test1.rb

$ ./test2.rb 
$0            : ./test2.rb
__FILE__      : ./test2.rb
$PROGRAM_NAME : ./test2.rb

起動する ruby test.rb をスクリプト名の任意のバリエーションで起動すると、一貫した結果が得られます。

呼び出されたファイル名のみが必要な場合は、File の basename メソッドを使うか、デリミタで分割して最後の要素を取ります。

$0__FILE__ は若干の違いがありますが、単一のスクリプトでは同等です。

puts File.basename($0)

を使用することには、いくつかの利点があります。 File.basename , File.extnameFile.dirname の一連のメソッドです。 basename はオプションのパラメータを取りますが、これは取り除くべき拡張子です。

File.basename($0, File.extname($0)) 

は、車輪の再発明や、可変長拡張子、欠落した拡張子、拡張子チェーンの不正な切り詰めの可能性に対処する必要なく、これを実現します。 .rb.txt などです。

ruby-1.9.2-p136 :004 > filename = '/path/to/file/name.ext'
 => "/path/to/file/name.ext" 
ruby-1.9.2-p136 :005 > File.basename(filename, File.extname(filename))
 => "name" 
ruby-1.9.2-p136 :006 > filename = '/path/to/file/name.ext' << '.txt'
 => "/path/to/file/name.ext.txt" 
ruby-1.9.2-p136 :007 > File.basename(filename, File.extname(filename))
 => "name.ext"