2009-07-16 17 views

答えて

17

Rubyコア(リンク先のstdlibではなく)のDir#tmpdir関数はクロスプラットフォームでなければなりません。

この機能を使用するには、require 'tmpdir'が必要です。

+3

これは、OSのグローバルな一時パスを提供しますが、アプリ独自の空のパスは提供しません。 – Mike

+1

マイクと同意する、私はこれが上記の質問に対する正解ではないと思う。私たちが必要とするものは、Tempfile(http://ruby-doc.org/stdlib/libdoc/tempfile/rdoc/files/tempfile_rb.html)に似ていますが、dirsの場合はそうです。理想的にはディレクトリを直接サポートするTempfileです。 – inger

+0

ええ、この回答は偽です。他のものはより正確です。私のhttp://stackoverflow.com/questions/1139265/what-is-the-best-way-to-get-a-temporary-directory-in-ruby-on-rails/8823618#8823618 – AlexChaffee

0

私はTempfileをハイジャックしてこれに取り組み始めました。以下を参照してください。 Tempfileのように自分自身をきれいにする必要がありますが、必ずしもそうではありません。 tempdirのファイルを削除するのはまだありません。 とにかく私はここでこれを共有しているので、出発点として役立つかもしれません。

require 'tempfile' 
class Tempdir < Tempfile 
    require 'tmpdir' 
    def initialize(basename, tmpdir = Dir::tmpdir) 
    super 
    p = self.path 
    File.delete(p) 
    Dir.mkdir(p) 
    end 
    def unlink # copied from tempfile.rb 
    # keep this order for thread safeness 
    begin 
     Dir.unlink(@tmpname) if File.exist?(@tmpname) 
     @@cleanlist.delete(@tmpname) 
     @data = @tmpname = nil 
     ObjectSpace.undefine_finalizer(self) 
    rescue Errno::EACCES 
     # may not be able to unlink on Windows; just ignore 
    end 
    end 
end 

これは例えば一時ファイル、同じように使用することができます:一時ファイルのすべてのメソッド

Tempdir.new('foo') 

を、そして今度は、ファイルが動作するはずです。 ただ簡単にテストしたので、保証はありません。

0

は、Ruby STEMPライブラリをチェックアウト:http://ruby-stemp.rubyforge.org/rdoc/

あなたはこのような何か場合:

dirname = STemp.mkdtemp("#{Dir.tmpdir}/directory-name-template-XXXXXXXX") 

dirnameは、以前に存在しないことが保証のディレクトリを指す文字列になりますが。ディレクトリ名をどのようなものから始めたいかを定義します。 Xはランダムな文字に置き換えられます。

EDIT:これは1.9で動作しませんでしたので、YMMVです。

2
require 'tmpdir' # not needed if you are loading Rails 
tmp_dir = File.join(Dir::tmpdir, "my_app_#{Time.now.to_i}_#{rand(100)}") 
Dir.mkdir(tmp_dir) 

Works for me。

+0

あなたは特定の確率で働くことを意味します:) – Alexey

11

私が今使っているおよそ10mlの液体フッ化水素を圧入一般:

def in_tmpdir 
    path = File.expand_path "#{Dir.tmpdir}/#{Time.now.to_i}#{rand(1000)}/" 
    FileUtils.mkdir_p path 
    yield path 
ensure 
    FileUtils.rm_rf(path) if File.exists?(path) 
end 

をそうすることができますあなたのコード内で:

in_tmpdir do |tmpdir| 
    puts "My tmp dir: #{tmpdir}" 
    # work with files in the dir 
end 

あなたのメソッドが終了しますとき、一時ディレクトリが自動的にに削除されます。

+1

非常に良いアプローチ、+1 – klaffenboeck

+3

この動作は既に[Dir.mktmpdir](http://ruby-doc.org/stdlib-1.9.3/libdoc/)に実装されています。 tmpdir/rdoc/Dir.html#method-c-mktmpdir) – fguillen

+1

私には 'in_tmpdir'という名前はブロックの文脈で' pwd'が変わることを示唆しています。パスを生成するのではなく、 'Dir.chdir(path、&block)'を使うことをお勧めします。 – tfischbach

0

更新:gem install files、その後、

require "files" 
dir = Files do 
    file "hello.txt", "stuff" 
end 

は、より多くの例については、以下を参照してください。


これは別の解決策ですが、他にもいくつかの回答があります。これはテストに含めるのに適しています(例:rspecまたはspec_helper.rb)。インクルードファイルの名前に基づいて一時的なディレクトリを作成し、テストの間持続するようにインスタンス変数に格納します(ただし、テスト間では共有されません)。終了時に削除されます(または、試運転後に内容を確認したい場合)。

def temp_dir options = {:remove => true} 
    @temp_dir ||= begin 
    require 'tmpdir' 
    require 'fileutils' 
    called_from = File.basename caller.first.split(':').first, ".rb" 
    path = File.join(Dir::tmpdir, "#{called_from}_#{Time.now.to_i}_#{rand(1000)}") 
    Dir.mkdir(path) 
    at_exit {FileUtils.rm_rf(path) if File.exists?(path)} if options[:remove] 
    File.new path 
    end 
end 

(あなたはまた、Rubyの1.8.7以来の周りされているDir.mktmpdirを(使用できる)の代わりに、Dir.mkdirが、私は命名アルゴリズムはもちろんのこと、そのメソッドのAPIが混乱を見つける。)

使い方例(および他の有用な試験方法):

def write name, contents = "contents of #{name}" 
    path = "#{temp_dir}/#{name}" 
    File.open(path, "w") do |f| 
    f.write contents 
    end 
    File.new path 
end 

describe "#write" do 
    before do 
    @hello = write "hello.txt" 
    @goodbye = write "goodbye.txt", "farewell" 
    end 

    it "uses temp_dir" do 
    File.dirname(@hello).should == temp_dir 
    File.dirname(@goodbye).should == temp_dir 
    end 

    it "writes a default value" do 
    File.read(@hello).should == "contents of hello.txt" 
    end 

    it "writes a given value" do 
    # since write returns a File instance, we can call read on it 
    @goodbye.read.should == "farewell" 
    end 
end 

アップデート:私はfiles WHIを呼んでいる宝石をキックスタートするために、このコードを使用しましたchは、一時的にディレクトリやファイルを作成することを非常に簡単にしたいと考えています。ユニットテスト)を使用する。 https://github.com/alexch/filesおよびhttps://rubygems.org/gems/filesを参照してください。

42
require "files" 

files = Files do  # creates a temporary directory inside Dir.tmpdir 
    file "hello.txt"   # creates file "hello.txt" containing "contents of hello.txt" 
    dir "web" do    # creates directory "web" 
    file "snippet.html", # creates file "web/snippet.html"... 
     "<h1>Fix this!</h1>" # ...containing "<h1>Fix this!</h1>" 
    dir "img" do   # creates directory "web/img" 
     file File.new("data/hello.png")   # containing a copy of hello.png 
     file "hi.png", File.new("data/hello.png") # and a copy of hello.png named hi.png 
    end 
    end 
end       # returns a string with the path to the directory 

Dirオブジェクトが一時ディレクトリを作成する方法mktmpdir有する:例えば

require 'tmpdir' # Not needed if you are using rails. 

Dir.mktmpdir do |dir| 
    puts "My new temp dir: #{dir}" 
end 

を一時ディレクトリは、ブロックの実行後に除去されるであろう。

+1

これはブロックにコードを収める必要があると思いますが、私はそれが好きです:) – rogerdpack

+8

[ruby-doc.org](http://ruby-doc.org/stdlib-2.0.0) /libdoc/tmpdir/rdoc/Dir.html#method-c-mktmpdir) _ブロックが指定されていない場合は、ディレクトリのパスが返されます。この場合、:: mktmpdirはディレクトリを削除しません。 – thinkOfaNumber

+1

あなたのコードをブロックに収めるにはどうすればいいですか?それが大きすぎる場合は、クラス/メソッド/ etcを作成してブロックから呼び出してください。 –

0

RubyにはDir#mktmpdirがあるので、それを使用してください。

require 'tempfile' 
Dir.mktmpdir('prefix_unique_to_your_program') do 
    ### your work here ### 
end 

これだけ速いTEMPDIRを構築するためにそれを使用する。、http://www.ruby-doc.org/stdlib-1.9.3/libdoc/tmpdir/rdoc/Dir.html

を参照するか、またはプロセスであるあなた自身の使用する一時ファイルの一時ファイルを作成し、独自のスレッド

require 'tempfile' 
Tempfile.open('prefix_unique_to_your_program') do |tmp| 
    tmp_dir = tmp.path + "_dir" 
    begin 
    FileUtils.mkdir_p(tmp_dir) 

    ### your work here ### 
    ensure 
    FileUtils.rm_rf(tmp_dir) 
    end 
end 

オプションの接尾辞/プレフィックスオプションのhttp://www.ruby-doc.org/stdlib-1.9.3/libdoc/tempfile/rdoc/Tempfile.htmlを参照してください。

0

Dir.mktmpdirを使用できます。

ブロックを使用すると、一時ディレクトリを閉じるとブロックが終了します。例えば

context 'when there are duplicate tasks' do 
    it 'raises an DuplicateTask error' do 
    begin 
     tmp_dir1 = Dir.mktmpdir('foo') 
     tmp_dir2 = Dir.mktmpdir('bar') 

     File.new("#{tmp_dir1}/task_name", 'w+') 
     File.new("#{tmp_dir2}/task_name", 'w+') 

     expect { subject.filepath('task_name') }.to raise_error(TaskFinder::DuplicateTask) 
    ensure 
     FileUtils.remove_entry tmp_dir1 
     FileUtils.remove_entry tmp_dir2 
    end 
    end 
end 

Dir.mktmpdirDir.tmpdirの下に一時ディレクトリを作成します

Dir.mktmpdir do |dir| 
    File.open("#{dir}/foo", 'w') { |f| f.write('foo') } 
end 

それとも、同時に存在する複数の一時ディレクトリが必要な場合は、(あなたはそれがに評価するか見てrequire 'tmpdir'する必要があります)。

独自のパスを使用する場合は、Dir.mktmpdirは、任意の2番目の引数tmpdirを指定します(nil以外の値が指定されている場合)。例えば。

Dir.mktmpdir(nil, "/var/tmp") { |dir| "dir is '/var/tmp/d...'" } 
関連する問題