web-dev-qa-db-ja.com

スレッドセーフな一時ファイル名の作成

Tempfile Rubyを使用すると、スレッドセーフでプロセス間セーフな名前のファイルが作成されます。必要なのはその方法だけです。

私は、次のようなより直接的なアプローチ方法があるかどうか疑問に思いました。

t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink
32
iltempo

Dir :: Tmpname.create

Dir::Tmpname.createを使用できます。使用する一時ディレクトリを特定します(ディレクトリを渡さない限り)。ブロックを期待していることを考えると、使用するのは少し醜いです:

require 'tmpdir'
# => true
Dir::Tmpname.create(['prefix-', '.ext']) {}
# => "/tmp/prefix-20190827-1-87n9iu.ext"
Dir::Tmpname.create(['prefix-', '.ext'], '/my/custom/directory') {}
# => "/my/custom/directory/prefix-20190827-1-11x2u0h.ext"

このブロックは、ファイルが存在するかどうかをテストし、Errno::EEXISTを発生させて、末尾に増分値を追加して新しい名前を生成できるようにするコード用にあります。

Railsソリューション

Ruby on Rails によって実装されたソリューションは短く、Rubyで最初に実装されたソリューションに似ています。

require 'tmpdir'
# => true
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{Rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-wyouwg-YOUR_SUFFIX"
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{Rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-140far-YOUR_SUFFIX"

Dir :: Tmpname.make_tmpname(Ruby 2.5.0以前)

Dir :: Tmpname.make_tmpnameはRuby 2.5.0で削除されました。Ruby 2.4.4より前は、プレフィックスとしてディレクトリパスを受け入れることができましたが、 of Ruby 2.4.4、ディレクトリ区切り文字が削除されます。

tempfile.rbを掘り下げると、TempfileDir::Tmpnameが含まれていることがわかります。中には make_tmpname があります。これはあなたが求めていることを実行します。

require 'tmpdir'
# => true
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname("prefix-", nil))
# => "/tmp/prefix-20190827-1-dfhvld"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], nil))
# => "/tmp/prefix-20190827-1-19zjck1.ext"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], "suffix"))
# => "/tmp/prefix-20190827-1-f5ipo7-suffix.ext"
56
Jan

Dir::Tmpname.make_tmpname was Ruby 2.5. で削除されました。これはSecureRandomの使用にフォールバックします。

require "tmpdir"

def generate_temp_filename(ext=".png")
  filename = begin
    Dir::Tmpname.make_tmpname(["x", ext], nil)
  rescue NoMethodError
    require "securerandom"
    "#{SecureRandom.urlsafe_base64}#{ext}"
  end
  File.join(Dir.tmpdir, filename)
end
2
Abe Voelker

ファイル名だけが必要なので、 SecureRandom を使用するのはどうですか?

require 'securerandom'

filename =  "#{SecureRandom.hex(6)}.png" #=> "0f04dd94addf.png"

SecureRandom.alphanumericを使用することもできます

0
Paulo Fidalgo