Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the name of the command called for usage prompts in Ruby?

I wrote a nice little Ruby script a while back that I'm rather fond of. I'd like to improve its robustness by checking for the proper number of arguments:

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

Of course that's pseudocode. Anyways, in C or C++ I could use argv[0] to get the name that the user used to get to my command, whether they called it like ./myScript.rb or myScript.rb or /usr/local/bin/myScript.rb. In Ruby, I know that ARGV[0] is the first true argument, and ARGV does not contain the command name. Is there any way that I can get this?

like image 939
adam_0 Avatar asked Jan 29 '11 02:01

adam_0


People also ask

How do I get command-line arguments in ruby?

In your Ruby programs, you can access any command-line arguments passed by the shell with the ARGV special variable. ARGV is an Array variable which holds, as strings, each argument passed by the shell.

How do I run a command-line in ruby?

Press Ctrl twice to invoke the Run Anything popup. Type the ruby script. rb command and press Enter . If necessary, you can specify the required command-line options and script arguments.

What is Stdin ruby?

The $stdin is a global variable that holds a stream for the standard input. It can be used to read input from the console. reading.rb. #!/usr/bin/ruby inp = $stdin.read puts inp. In the above code, we use the read method to read input from the console.


1 Answers

Ruby has three ways of giving us the name of the called script:

#!/usr/bin/env ruby  puts "$0            : #{$0}" puts "__FILE__      : #{__FILE__}" puts "$PROGRAM_NAME : #{$PROGRAM_NAME}" 

Saving that code as "test.rb" and calling it a couple ways shows that the script receives the name as it was passed to it by the OS. A script only knows what the OS tells it:

$ ./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 

Calling it using the ~ shortcut for $HOME in the second example shows the OS replacing it with the expanded path, matching what is in the third example. In all cases it's what the OS passed in.

Linking to the file using both hard and soft links shows consistent behavior. I created a hard link for test1.rb and a soft link for 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 

Launching ruby test.rb with any of the variations on the script name returns consistent results.

If you only want the called filename, you can use File's basename method with one of the variables or split on the delimiter and take the last element.

$0 and __FILE__ have some minor differences but for single scripts they're equivalent.

puts File.basename($0) 

There are some benefits to using the File.basename,File.extname and File.dirname suite of methods. basename takes an optional parameter, which is the extension to strip, so if you need just the basename without the extension

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

does it without reinventing the wheel or having to deal with variable-length or missing extensions or the possibility of incorrectly truncating extension chains ".rb.txt" for instance:

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"  
like image 57
the Tin Man Avatar answered Sep 28 '22 13:09

the Tin Man