

環境はMacとCentOSを考えています。

`~/hoge/ruby.rb`というプログラムをターミナルから実行するには、通常`$ruby ~/hoge/ruby.rb`とする必要がありますが、
これを`$hoge -option`という感じで実行することはできますか?

可能であればどのような手順、知識が必要なのか、またそうすること自体に問題があるかどうか教えてください。


CC BY-SA 3.0
2014-12-17T02:03:04.170
1833
2014-12-17T14:31:12.253
4310
question
ruby
rubyで作ったプログラムをターミナルからコマンドで実行したい。


Shell Scriptを書くのではだめでしょうか？

[code]

    #!/bin/sh
    ruby ~hoge/ruby.rb $1
    
[/code]

というファイルをhogeという名前で保存してchmod +xした後pathの通っているところに置いておけば、 $hoge
-optionで動作すると思います。（optionは、$1に入ります）


CC BY-SA 3.0
2014-12-17T02:14:41.143
1835
2014-12-17T02:14:41.143
3178
1833
answer


Unix互換やLinuxシステムでは、ファイルの先頭行にインタプリタを指定する事で、そのスクリプトの起動時に、特定のインタプリタで実行させる事が出来ます。

具体的には、rubyスクリプトファイルの1行目に以下の様に書き込みます。

[code]

    #!/usr/bin/env ruby
    
[/code]

その上で、ファイルに実行権限を付与することで、直接起動させることが可能です。

[code]

    $ chmod +x ~/hoge/ruby.rb
    $ ~/hoge/ruby.rb
    
[/code]

`~/hoge/ruby.rb` を `path` の通った所に `hoge`
にリネーム、もしくはシンボリックリンクを作成するなどして置くことで、`hogeコマンド`として利用出来ます。

なお、この1行目の（`#!`から始まる）記述は`shebang`と呼ばれます。
詳細は[Wikipedia](http://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_%28Unix%29)などで確認してください。


CC BY-SA 3.0
2014-12-17T02:16:23.293
1837
2014-12-17T02:24:15.793
2014-12-17T02:24:15.793
2944
2944
1833
answer


madapajaさんの投稿への補足ですが、多くのOSでは`shebang`は引数を1つしか取れなかったと思うので、`#!/usr/bin/env
ruby`では「ruby」が引数となってしまい、`ruby`へコマンドライン引数を渡せません。

[code]

    #!/bin/sh
    exec ruby -S -x "$0" ${@+"$@"}
    #!ruby
    # 以下、ruby.rbの中身を記述。ARGVにコマンドライン引数が入ります。
    
[/code]

のように一旦シェルスクリプトから`ruby`を実行することで、コマンドライン引数を渡せます。 `ruby`は`#!ruby`までの行を読み飛ばしてくれます。

尚、`chmod +x`で実行権限を与える必要があります。


CC BY-SA 3.0
2014-12-17T02:30:26.140
1840
2014-12-17T02:30:26.140
3313
1833
answer


次の手順を踏むことで、スクリプトを `$ ruby.rb -option` として実行できます。（お書きのとおり `$ hoge -option`
として実行するなら、スクリプトを `hoge` にリネームしてください）

  * スクリプトの1行目に `#!/usr/bin/env ruby` と書く
  * `chmod +x ~/hoge/ruby.rb` を実行する
  * 環境変数 `PATH` に `$HOME/hoge` を追加する、または `ruby.rb` をパスの通ったディレクトリに移動する

各手順で何をしているか解説します。

テキストファイルの1行目に `#!（プログラムへの絶対パス）` と書いた行は Shebang 行と呼ばれるもので、
そのファイルをスクリプトとして実行するためのプログラムを指定します。 `/usr/bin/env ruby` は環境変数 `PATH`
に指定されたディレクトリから `ruby` を探し、それを実行します。 `#!/usr/local/bin/ruby`
のように直接指定することもできますが、環境によって `ruby` のパスが違うこともあるので、前者のように書くことをおすすめします。

`chmod +x ~/hoge/ruby.rb` は、現在のユーザーが `~/hoge/ruby.rb`
をプログラムとして実行できるように、ファイルにパーミッションを付加します。詳しくは `$ man chmod` を参照してください。

環境変数 `PATH` は、プログラムを検索するディレクトリを設定するためのものです（設定することを「パスを通す」などと言います）。 `$ echo
$PATH` を実行すると、 `/usr/local/bin:/usr/bin:...` などと設定されているのが分かります。 `PATH`
に書かれているディレクトリ内のプログラムは、パスを指定しなくともプログラム名だけで実行できるようになります。よって、プログラムをコマンドとして実行するためには、プログラムを含むディレクトリにパスを通すか、パスの通ったディレクトリにプログラムを移動します。

パスを設定するには、 Bash の場合 `~/.bash_profile` に `export PATH=/hoge/fuga/dir:$PATH`
と書きます。詳しくは「path bash」などで検索してください。


CC BY-SA 3.0
2014-12-17T02:33:08.687
1842
2014-12-17T02:33:08.687
2259
1833
answer


原理から説明します。

GUI 上のファイルマネージャ(例:
Windowsのexplorer、Linuxのnautilus)はファイルの中身や拡張子からそれが「rubyのスクリプトだ」と判断しています。
ですのでダブルクリックした際は自動で

[code]

    ruby /home/mattn/hoge/ruby.rb
    
[/code]

というコマンドが実行される様になっています。かたやターミナル、つまりシェルから実行する際はその辺は自動で行ってくれません。
ただしスクリプトファイルに2点手を入れる事で、GUI からでもターミナルからでも実行できる様に出来ます。

# shebang の付与

上記でも書かれていますが、UNIX 系 OS ではファイルの先頭に

[code]

    #!インタプリタの実行方法
    
[/code]

という行を付与する事で、そのファイルを実行する際の方法を指定する事が出来ます。つまり拡張子 `.rb` と言いながら perl
で起動するという事も出来ます。 尚、OS によってインタプリタがインストールされる場所が異なる為

[code]

    #!/usr/bin/env ruby
    
[/code]

と書くのが一般的です。env は引数で与えられたコマンドを PATH 環境変数から解決して実行してくれます。

# 実行権限の付与

shebang を付与しただけでは実行できません。以下のコマンドを実行して、コマンドラインから直接実行出来る様にします。

[code]

    chmod +x ~/hoge/ruby.rb
    
[/code]

これで GUI 上のファイルマネージャ等からでもダブルクリックで起動でき、ターミナルからでも実行できるコマンドとなりました。

なお、この上記2つの対応を入れる事で、ファイルの拡張子は必要なくなりますので、パスの通った場所に自由な名前で置いて頂くと名前だけで実行出来る様になります。


CC BY-SA 3.0
2014-12-17T02:34:19.897
1843
2014-12-17T02:55:50.313
2014-12-17T02:55:50.313
440
440
1833
answer


Rubyスクリプトの一行目に以下のようにhashbangを入れます。

[code]

    #!/usr/bin/env ruby
    p ARGV
    
[/code]

例として、上記のコードをテキストファイル`foo`に書いた後、シェルで以下のように実行するとします。

[code]

    $ chmod +x foo
    $ ./foo bar
    
[/code]

`["bar"]`が出力され、引数を取れていることが確認出来るはずです。

_（手元の環境ではMac OSXとUbuntu上のzsh, bash, tcshで確認出来ました）_

  * `chmod +x`でコマンドとして実行するための権限を追加しています
  * `/usr/local/bin`などパスが通っているディレクトリにスクリプトを置けば、相対パスで実行しなくてもよいです。


CC BY-SA 3.0
2014-12-17T02:50:49.917
1846
2014-12-17T02:50:49.917
2213
1833
answer


rails のコマンドは rails new とか、rails generate model のように実行をします。  
実は この rails のコマンドの実体は ruby スクリプトです。

$ which rails とすると、ファイル名がわかります。  
そのファイル名を cat するなり、editor で開くなどしてみてください。  
こんなふうになっているはずです。  
以下は MacOS X に rbenv で ruby をいれている私のマシンでの場合です。

[code]

    $ which rails
    /Users/katoy/.rbenv/shims/rails
    
    $ cat /Users/katoy/.rbenv/shims/rails
    #!/usr/bin/env bash
    set -e
    [ -n "$RBENV_DEBUG" ] && set -x
    
    program="${0##*/}"
    if [ "$program" = "ruby" ]; then
      for arg; do
        case "$arg" in
        -e* | -- ) break ;;
        */* )
          if [ -f "$arg" ]; then
            export RBENV_DIR="${arg%/*}"
            break
          fi
          ;;
        esac
      done
    fi
    
    export RBENV_ROOT="/Users/katoy/.rbenv"
    exec "/usr/local/Cellar/rbenv/0.4.0/libexec/rbenv" exec "$program" "$@"
    
[/code]

こんなふうにして、ruby プログラムを通常のコマンドのように実行できるようにしているのです。  
rails 以外にも、このような方法で、 ruby スクリプトを 通常のコマンドのように実行できるようにしているものはたくさんあります。  
(rake, rspec, bundle, coffee-script, ...)

もし本格的に ruby でコマンドラインアプリケーションを作るなら、次の書籍がお勧めです。  
[Build Awesome Command-Line Applications in Ruby
2](https://pragprog.com/book/dccar2/build-awesome-command-line-applications-
in-ruby-2)


CC BY-SA 3.0
2014-12-17T14:31:12.253
1933
2014-12-17T14:31:12.253
2987
1833
answer