Dir.mktmpdirで一時的なディレクトリを作成する

`Dir.mktmpdir` 使ってますか？

Ruby プログラム中で temporary なディレクトリを作成したいことありますよね。
その時に役立つのが `Dir.mktmpdir` です。



## Dir.mktmpdir の使い方
```rb
require 'tmpdir'
```

としてから、

```rb
Dir.mktmpdir {|dir| p dir }
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-1golnp6"
```

もしくは、

```rb
Dir.mktmpdir do |dir|
  p dir
end
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-h3po3k"
```
のようにして使います。

`Dir.mktmpdir` を実行するたびに新しい一時ディレクトリが作成されます。



## Dir.mktmpdir の挙動について

`Dir.mktmpdir`にブロックを渡すと、ブロックを抜ける時に自動的に削除されます。

```rb
tmpdir = Dir.mktmpdir do |dir|
  p dir 
  #=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-1g0qgbr"

  Dir.exists? dir 
  #=> true
  
  dir
end

p tmpdir 
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-11g0nps"

# ブロックを抜けると自動的に削除されます
Dir.exists? tmpdir
#=> false
```

また、ブロックを渡さない場合、`Dir.mktmpdir` で作成したディレクトリは自動的に削除されないため、明示的に削除する必要があります。

```rb
tmpdir = Dir.mktmpdir
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-51kzdt"

begin
  Dir.exists? tmpdir
  #=> true
  
  File.open("#{tmpdir}/foo", "w") { |fp|
    fp.puts "hogehoge"
  }
ensure
  # tmpdir を削除
  FileUtils.remove_entry_secure tmpdir
end

Dir.exists? tmpdir
#=> false
```



## Dir.mktmpdir で作成されるディレクトリのプレフィクス(接頭辞)を変更する

`Dir.mktmpdir` の第1引数に文字列を与えると、プレフィクスを変更することができます。

```rb
Dir.mktmpdir("hoge") {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/hoge20140207-1906-1acnw8q"

Dir.mktmpdir("fuga") {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/fuga20140207-1906-1bnrbvj"

Dir.mktmpdir("piyo") {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/piyo20140207-1906-b6x8qf"
```

第1引数が nil または省略されると、プレフィクスは `d` になります。

```rb
Dir.mktmpdir(nil) {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-icruez"

Dir.mktmpdir {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-1906-1075ir0"
```

## Dir.mktmpdir で作成されるディレクトリのサフィックス(接尾辞)を変更する

`Dir.mktmpdir` の第1引数に文字列の配列を渡すことでプレフィクスとサフィックスを変更することができます。

```rb
Dir.mktmpdir(["hoge","fuga"]) {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/hoge20140207-1906-rwn5jbfuga"
```

```rb
# 第1引数の配列の3つ目移行の要素は無視される
Dir.mktmpdir(["hoge","fuga","piyo"]) {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/hoge20140207-1906-jyvsy7fuga"

# 第1引数の配列の1つ目を nil にするとプレフィクスが省略される。
# (デフォルトの`d`もつかない)
Dir.mktmpdir([nil,"fuga"]) {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/20140207-1906-5utqtmfuga"
```



## `Dir.mktmpdir` で一時ディレクトリが作成されるディレクトリのパスについて

`Dir.mktmpdir` の一時ディレクトリはどこに作成されるのでしょうか？

デフォルトでは `Dir.tmpdir` で返ってくるディレクトリパス以下に作成しているようです。
OSや環境によって `Dir.tmpdir` の値は異なりますが、Mac OS X に於いては環境変数 `$TMPDIR` または `/tmp` になるようです。
なお、`Dir.mktmpdir` の第2引数でパスを指定することにより、一時ディレクトリが作成される場所を変更することができます。

```rb
## デフォルト

Dir.mktmpdir {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-12915-1r83rgl"
```

```rb
## Dir.mktmpdir の第2引数でパスを指定する

Dir.mktmpdir(nil, "/var/tmp") {|dir| p dir}
#=> "/var/tmp/d20140207-12915-1bkxe2m"
```

```rb
## Dir.tmpdir の値を確認する

Dir.tmpdir
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T"

Dir.mktmpdir {|dir| p dir}
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/d20140207-12915-zxtexn"
```

```rb
## 環境変数 $TMPDIR を書き換える

p ENV['TMPDIR']
#=> "/var/folders/xm/gdpmzj1x7_ng04dk88dd0sb80000gp/T/"

ENV['TMPDIR'] = "/var/tmp"
p ENV['TMPDIR']
#=> "/var/tmp"

Dir.tmpdir
#=> "/var/tmp"

Dir.mktmpdir {|dir| p dir}
#=> "/var/tmp/d20140207-12915-182s4yn"
```

```rb
## 環境変数 $TMPDIR に存在しないディレクトリを指定する

ENV['TMPDIR'] = "/hogehoge/fugafuga/piyopiyo"
p ENV['TMPDIR']
#=> "/hogehoge/fugafuga/piyopiyo"

Dir.exists? ENV['TMPDIR']
#=> false

Dir.tmpdir
#=> "/tmp"

Dir.mktmpdir {|dir| p dir}
#=> "/tmp/d20140207-12915-161229z"
```

```rb
## 環境変数 $TMPDIR を空にする

ENV['TMPDIR'] = nil
p ENV['TMPDIR']
#=> nil

Dir.tmpdir
#=> "/tmp"

Dir.mktmpdir {|dir| p dir}
#=> "/tmp/d20140207-12915-1ltqeva"
```

以上のことから、以下の順番で`Dir.mktmpdir`のパスが決まるようです。

1. `Dir.mktmpdir` の第2引数で指定したパス
1. 1.が指定されていない場合は `Dir.tmpdir` の値
  1. 環境変数 `$TMPDIR` の値
  1. `$TMPDIR` が見つからない場合や `$TMPDIR` にアクセスできない場合は `/tmp`

## 参考URL

- [singleton method Dir.mktmpdir](http://docs.ruby-lang.org/ja/1.9.3/method/Dir/s/mktmpdir.html)
- [Class: Dir (Ruby 1.9.3)](http://ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html)
- [Rubyist Magazine - 標準添付ライブラリ紹介 【第 15 回】 tmpdir, tempfile](http://magazine.rubyist.net/?0029-BundledLibraries)