[Elixir]外部コマンドを叩く

#Goal
Elixirから外部のコマンドを実行する。

#Dev-Environment
OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.5

#Wait a minute
Elixirから外部コマンドのgitを叩いてみる。
gitのバージョンとヘルプの出力結果を取得する。

ここで言っている外部コマンドの定義。
外部コマンド = Elixirの外にあるコマンド

#Index
External command from Elixir
|> Find commad
|> Execute commad
|> Extra
|> Consideration

##Find commad
Elixirの外部にあるコマンドが存在するか確認します。

Example:

外部コマンドが存在しない場合。
nilが返ってくる。

```iex
iex> System.find_executable("hogehoge")
nil
```

外部コマンドが存在する場合。
パスが返ってくる。

```iex
iex> System.find_executable("git")
"path/to/git.exe"
```

##Execute commad
Elixirから外部コマンドを実行してみます。

Example:
まず、dateコマンドを叩いてみます。

```iex
iex> System.cmd("date", [])
{"Thu Sep 17 12:00:04     2015\n", 0}
```

戻ってくるのはタプルのようです。

続いて、gitのバージョンを取得してみましょう。

```iex
iex> System.cmd("git", ["--version"])
{"git version 2.1.0\n", 0}
```

ついでに、ヘルプオプションを呼び出してみる。

```iex
iex> {result, 0} = System.cmd("git", ["--help"])
{"usage: git [--version] [--help] [-C <path>] [-c name=value]\n           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n           [-p|--paginate|--no-pager] [--
no-replace-objects] [--bare]\n           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n           <command> [<args>]\n\nThe most commonly used git commands are:\n
 add        Add file contents to the index\n   bisect     Find by binary search the change that introduced a bug\n   branch     List, create, or delete branches\n   checkout   Chec
kout a branch or paths to the working tree\n   clone      Clone a repository into a new directory\n   commit     Record changes to the repository\n   diff       Show changes betwee
n commits, commit and working tree, etc\n   fetch      Download objects and refs from another repository\n   grep       Print lines matching a pattern\n   init       Create an empt
y Git repository or reinitialize an existing one\n   log        Show commit logs\n   merge      Join two or more development histories together\n   mv         Move or rename a file
, a directory, or a symlink\n   pull       Fetch from and integrate with another repository or a local branch\n   push       Update remote refs along with associated objects\n   re
base     Forward-port local commits to the updated upstream head\n   reset      Reset current HEAD to the specified state\n   rm         Remove files from the working tree and from
 the index\n   show       Show various types of objects\n   status     Show the working tree status\n   tag        Create, list, delete or verify a tag object signed with GPG\n\n'g
it help -a' and 'git help -g' lists available subcommands and some\nconcept guides. See 'git help <command>' or 'git help <concept>'\nto read about a specific subcommand or concept
.\n",
 0}
iex> IO.puts result
usage: git [--version] [--help] [-C <path>] [-c name=value]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty Git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and integrate with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

'git help -a' and 'git help -g' lists available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.

:ok
```

##Extra
組み合わせて使ってみる。

Example:
gitのブランチを取得してみる。


```iex
iex> cmd_path = System.find_executable("git")
"path/to/git.exe"
iex> if cmd_path do
...>   {result, 0} = System.cmd(cmd_path, ["branch"])
...> end
{"  ecto_update\n  filling_in_layout\n  following_users\n* master\n  modeling_users\n  sign_in_out\n  sign_up\n  static_pages\n  updating_users\n  user_microposts\n",
 0}
iex> IO.puts result
  ecto_update
  filling_in_layout
  following_users
* master
  modeling_users
  sign_in_out
  sign_up
  static_pages
  updating_users
  user_microposts

:ok
```

コマンドが見つからなければnilが返ってくるのを利用して、
if文でチェックできますね。

##Consideration
考察という名のメモ。

- mkdirを叩くと処理が戻ってこない

ディレクトリは作成されているが、処理が戻ってこない。

おそらく、結果が返ってくるタイプのコマンドでないと使えない気がする。
もしくは、cmd/3関数のオプションか何かで方法があると思われる。

~~詳しくは調べていないため、現状不明。~~
mkdirをしたいのであれば、Fileモジュールを使えばよいみたいです。

"mix phoenix.new"する時にディレクトリも作っていたと思います。
そこら辺を調べてもいいかもしれないですね。

- pingを叩くとbitstringが返ってくる

gitコマンドだと、人間の目で確認しやすい文字列で返ってくるのに、
pingを叩くとbitstringが返ってくる...この差異は何？
(コマンドプロンプトの文字コードの設定がutf8じゃないから？)

ここら辺は変換する方法があるので、必要になったら調べる程度。

- もう一つの方法

Erlangの[:os.cmd/1関数](http://www.erlang.org/doc/man/os.html#cmd-1)を使えば、外部コマンドを叩くことができるようです。(未検証)
...このコマンド、"mix phoenix.new"のソースファイル内で見た気がする。

#Speaking to oneself
少し検証が不足している部分があるが、必要になったら調べれば良し！
これで外部コマンドを呼び出して結果が取得できる！！

#Bibliography
[hexdocs - Elixir (v1.0.5) - System](http://elixir-lang.org/docs/v1.0/elixir/System.html)
[hexdocs - Elixir (v1.0.5) - System.cmd/3](http://elixir-lang.org/docs/v1.0/elixir/System.html#cmd/3)