類別 Dir

類別 Dir 的物件表示底層檔案系統中的目錄。

它主要包含

關於範例

此頁面上的部分範例使用這個簡單的檔案樹

example/
├── config.h
├── lib/
│   ├── song/
│   │   └── karaoke.rb
│   └── song.rb
└── main.rb

其他範例使用 Ruby 專案本身 的檔案樹。

Dir 作為陣列類似物件

Dir 物件在某些方面類似陣列

Dir 作為串流類似物件

Dir 物件在某些方面類似串流。

串流最初開啟供讀取,但可以手動關閉(使用 close 方法),如果串流是由帶有區塊的 Dir.open 建立的,則會在區塊結束時關閉。已關閉的串流不能再進一步處理,也不能重新開啟。

串流有一個 位置,它是目錄中項目的索引

範例(使用 簡單檔案樹

dir = Dir.new('example') # => #<Dir:example>
dir.pos                  # => 0

dir.read # => "."
dir.read # => ".."
dir.read # => "config.h"
dir.read # => "lib"
dir.read # => "main.rb"
dir.pos  # => 5
dir.read # => nil
dir.pos  # => 5

dir.rewind # => #<Dir:example>
dir.pos    # => 0

dir.pos = 3 # => 3
dir.pos     # => 3

dir.seek(4) # => #<Dir:example>
dir.pos     # => 4

dir.close # => nil
dir.read  # Raises IOError.

此處內容

首先,其他地方的內容。類別 Dir

在此,類別 Dir 提供對下列項目有用的方法

讀取

設定

查詢

反覆運算

其他

常數

SYSTMPDIR

系統範圍的暫時目錄路徑

公開類別方法

Dir[*patterns, base: nil, sort: true] → array 按一下以切換來源

呼叫 Dir.glob,並提供參數 patterns 以及關鍵字參數 basesort 的值;傳回所選項目名稱的陣列。

# File dir.rb, line 222
def self.[](*args, base: nil, sort: true)
  Primitive.dir_s_aref(args, base, sort)
end
chdir(new_dirpath) → 0 按一下以切換來源
chdir → 0
chdir(new_dirpath) {|new_dirpath| ... } → 物件
chdir {|cur_dirpath| ... } → 物件

變更目前工作目錄。

有參數 new_dirpath 且沒有區塊時,變更到指定的 dirpath

Dir.pwd         # => "/example"
Dir.chdir('..') # => 0
Dir.pwd         # => "/"

沒有參數且沒有區塊時

  • 如果已定義,變更到環境變數 HOME 的值。

  • 否則,如果已定義,變更到環境變數 LOGDIR 的值。

  • 否則,不進行任何變更。

有參數 new_dirpath 且有區塊時,暫時變更工作目錄

  • 使用參數呼叫區塊。

  • 變更到指定的目錄。

  • 執行區塊(產生新的路徑)。

  • 還原先前的目錄。

  • 傳回區塊的傳回值。

範例

Dir.chdir('/var/spool/mail')
Dir.pwd   # => "/var/spool/mail"
Dir.chdir('/tmp') do
  Dir.pwd # => "/tmp"
end
Dir.pwd   # => "/var/spool/mail"

沒有參數且有區塊時,使用目前工作目錄(字串)呼叫區塊,並傳回區塊的傳回值。

使用區塊呼叫 Dir.chdir 可以巢狀

Dir.chdir('/var/spool/mail')
Dir.pwd     # => "/var/spool/mail"
Dir.chdir('/tmp') do
  Dir.pwd   # => "/tmp"
  Dir.chdir('/usr') do
    Dir.pwd # => "/usr"
  end
  Dir.pwd   # => "/tmp"
end
Dir.pwd     # => "/var/spool/mail"

在多執行緒程式中,如果一個執行緒嘗試在另一個執行緒已開啟 chdir 區塊時開啟 chdir 區塊,或在傳遞給 chdir 的區塊內發生沒有區塊的 chdir 呼叫(即使在同一個執行緒中),會引發錯誤。

如果目標目錄不存在,會引發例外。

static VALUE
dir_s_chdir(int argc, VALUE *argv, VALUE obj)
{
    VALUE path = Qnil;

    if (rb_check_arity(argc, 0, 1) == 1) {
        path = rb_str_encode_ospath(rb_get_path(argv[0]));
    }
    else {
        const char *dist = getenv("HOME");
        if (!dist) {
            dist = getenv("LOGDIR");
            if (!dist) rb_raise(rb_eArgError, "HOME/LOGDIR not set");
        }
        path = rb_str_new2(dist);
    }

    return chdir_path(path, true);
}
children(dirpath) → 陣列 按一下以切換來源
children(dirpath, encoding: 'UTF-8') → 陣列

傳回 dirpath 目錄中項目名稱的陣列,但不包括 '.''..';將指定的編碼設定到每個傳回的項目名稱

Dir.children('/example') # => ["config.h", "lib", "main.rb"]
Dir.children('/example').first.encoding
# => #<Encoding:UTF-8>
Dir.children('/example', encoding: 'US-ASCII').first.encoding
# => #<Encoding:US-ASCII>

請參閱 字串編碼

如果目錄不存在,會引發例外。

static VALUE
dir_s_children(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    dir = dir_open_dir(argc, argv);
    return rb_ensure(dir_collect_children, dir, dir_close, dir);
}
chroot(dirpath) → 0 按一下以切換來源

將呼叫程式的根目錄變更為 dirpath 中指定的目錄。新的根目錄用於以 '/' 開頭的路徑名稱。根目錄會由呼叫程式的所有子程式繼承。

只有特權程式可以呼叫 chroot

請參閱 Linux chroot

static VALUE
dir_s_chroot(VALUE dir, VALUE path)
{
    path = check_dirname(path);
    if (chroot(RSTRING_PTR(path)) == -1)
        rb_sys_fail_path(path);

    return INT2FIX(0);
}
rmdir(dirpath) → 0 按一下以切換來源

從底層檔案系統中移除 dirpath 的目錄

Dir.rmdir('foo') # => 0

如果目錄不為空,則引發例外。

static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
    const char *p;
    int r;

    dir = check_dirname(dir);
    p = RSTRING_PTR(dir);
    r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0);
    if (r < 0)
        rb_sys_fail_path(dir);

    return INT2FIX(0);
}
each_child(dirpath) {|entry_name| ... } → nil 按一下以切換來源
each_child(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil

Dir.foreach 相同,但不會包含項目 '.''..'

static VALUE
dir_s_each_child(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    RETURN_ENUMERATOR(io, argc, argv);
    dir = dir_open_dir(argc, argv);
    rb_ensure(dir_each_child, dir, dir_close, dir);
    return Qnil;
}
empty?(dirpath) → true 或 false 按一下以切換來源

傳回 dirpath 是否指定一個空目錄

dirpath = '/tmp/foo'
Dir.mkdir(dirpath)
Dir.empty?(dirpath)            # => true
Dir.empty?('/example')         # => false
Dir.empty?('/example/main.rb') # => false

如果 dirpath 未在底層檔案系統中指定目錄或檔案,則引發例外。

static VALUE
rb_dir_s_empty_p(VALUE obj, VALUE dirname)
{
    VALUE result, orig;
    const char *path;
    enum {false_on_notdir = 1};

    FilePathValue(dirname);
    orig = rb_str_dup_frozen(dirname);
    dirname = rb_str_encode_ospath(dirname);
    dirname = rb_str_dup_frozen(dirname);
    path = RSTRING_PTR(dirname);

#if defined HAVE_GETATTRLIST && defined ATTR_DIR_ENTRYCOUNT
    {
        u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
        struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
        if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
            rb_sys_fail_path(orig);
        if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
            al.commonattr = 0;
            al.dirattr = ATTR_DIR_ENTRYCOUNT;
            if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
                if (attrbuf[0] >= 2 * sizeof(u_int32_t))
                    return RBOOL(attrbuf[1] == 0);
                if (false_on_notdir) return Qfalse;
            }
            rb_sys_fail_path(orig);
        }
    }
#endif

    result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path,
                                            RUBY_UBF_IO, 0);
    if (FIXNUM_P(result)) {
        rb_syserr_fail_path((int)FIX2LONG(result), orig);
    }
    return result;
}
entries(dirname, encoding: 'UTF-8') → 陣列 按一下以切換來源

傳回 dirpath 目錄中的項目名稱陣列;設定每個傳回項目名稱的編碼

Dir.entries('/example') # => ["config.h", "lib", "main.rb", "..", "."]
Dir.entries('/example').first.encoding
# => #<Encoding:UTF-8>
Dir.entries('/example', encoding: 'US-ASCII').first.encoding
# => #<Encoding:US-ASCII>

請參閱 字串編碼

如果目錄不存在,會引發例外。

static VALUE
dir_entries(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    dir = dir_open_dir(argc, argv);
    return rb_ensure(dir_collect, dir, dir_close, dir);
}
exist?(dirpath) → true 或 false 按一下以切換來源

傳回 dirpath 是否為底層檔案系統中的目錄

Dir.exist?('/example')         # => true
Dir.exist?('/nosuch')          # => false
Dir.exist?('/example/main.rb') # => false

File.directory? 相同。

VALUE
rb_file_directory_p(void)
{
}
fchdir(fd) → 0 按一下以切換來源
fchdir(fd) { ... } → 物件

將目前工作目錄變更為整數檔案描述符 fd 指定的目錄。

在透過 UNIX socket 或傳遞給子程序時,使用 fchdir 代替 chdir 可避免 檢查時間到使用時間的漏洞

沒有區塊時,變更為 fd 給定的目錄

Dir.chdir('/var/spool/mail')
Dir.pwd # => "/var/spool/mail"
dir  = Dir.new('/usr')
fd = dir.fileno
Dir.fchdir(fd)
Dir.pwd # => "/usr"

有區塊時,暫時變更工作目錄

  • 使用參數呼叫區塊。

  • 變更到指定的目錄。

  • 執行區塊(不產生引數)。

  • 還原先前的目錄。

  • 傳回區塊的傳回值。

範例

Dir.chdir('/var/spool/mail')
Dir.pwd # => "/var/spool/mail"
dir  = Dir.new('/tmp')
fd = dir.fileno
Dir.fchdir(fd) do
  Dir.pwd # => "/tmp"
end
Dir.pwd # => "/var/spool/mail"

此方法使用 POSIX 2008 定義的 fchdir() 函式;此方法未在非 POSIX 平台上實作(引發 NotImplementedError)。

如果檔案描述符無效,則引發例外。

在多執行緒程式中,如果一個執行緒嘗試在另一個執行緒已開啟 chdir 區塊時開啟 chdir 區塊,或在傳遞給 chdir 的區塊內發生沒有區塊的 chdir 呼叫(即使在同一個執行緒中),會引發錯誤。

static VALUE
dir_s_fchdir(VALUE klass, VALUE fd_value)
{
    int fd = RB_NUM2INT(fd_value);

    if (chdir_blocking > 0) {
        if (rb_thread_current() != chdir_thread)
            rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
        if (!rb_block_given_p())
            rb_warn("conflicting chdir during another chdir block");
    }

    if (rb_block_given_p()) {
        struct fchdir_data args;
        args.old_dir = dir_s_alloc(klass);
        dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil);
        args.fd = fd;
        args.done = FALSE;
        return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args);
    }
    else {
        int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_fchdir, &fd,
                                                       RUBY_UBF_IO, 0);
        if (r < 0)
            rb_sys_fail("fchdir");
    }

    return INT2FIX(0);
}
for_fd(fd) → dir 按一下以切換來源

傳回新的 Dir 物件,代表由給定的整數目錄檔案描述符 fd 指定的目錄

d0 = Dir.new('..')
d1 = Dir.for_fd(d0.fileno)

請注意,傳回的 d1 沒有關聯路徑

d0.path # => '..'
d1.path # => nil

此方法使用 POSIX 2008 定義的 fdopendir() 函式;此方法未在非 POSIX 平台上實作(引發 NotImplementedError)。

static VALUE
dir_s_for_fd(VALUE klass, VALUE fd)
{
    struct dir_data *dp;
    VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);

    if (!(dp->dir = fdopendir(NUM2INT(fd)))) {
        rb_sys_fail("fdopendir");
        UNREACHABLE_RETURN(Qnil);
    }

    RB_OBJ_WRITE(dir, &dp->path, Qnil);
    return dir;
}
foreach(dirpath, encoding: 'UTF-8') {|entry_name| ... } → nil 按一下以切換來源

使用 dirpath 中目錄中的每個項目名稱呼叫區塊;設定每個傳遞的 entry_name 的編碼

Dir.foreach('/example') {|entry_name| p entry_name }

輸出

"config.h"
"lib"
"main.rb"
".."
"."

編碼

Dir.foreach('/example') {|entry_name| p entry_name.encoding; break }
Dir.foreach('/example', encoding: 'US-ASCII') {|entry_name| p entry_name.encoding; break }

輸出

#<Encoding:UTF-8>
#<Encoding:US-ASCII>

請參閱 字串編碼

如果沒有給定區塊,傳回一個列舉器。

static VALUE
dir_foreach(int argc, VALUE *argv, VALUE io)
{
    VALUE dir;

    RETURN_ENUMERATOR(io, argc, argv);
    dir = dir_open_dir(argc, argv);
    rb_ensure(dir_each, dir, dir_close, dir);
    return Qnil;
}
pwd → string 按一下以切換來源

傳回目前工作目錄的路徑

Dir.chdir("/tmp") # => 0
Dir.pwd           # => "/tmp"
static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}
glob(*patterns, flags: 0, base: nil, sort: true) → array 按一下以切換來源
glob(*patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } → nil

形成一個陣列 entry_names,其中包含由參數選取的項目名稱。

參數 patterns 是字串樣式或字串樣式陣列;請注意,這些不是正規表示式;請見下方。

下列範例的注意事項

  • '*' 是與除了以 '.' 開頭的項目名稱以外的任何項目名稱相符的樣式。

  • 我們使用 Array#take 方法來縮短傳回的陣列,否則陣列會非常龐大。

如果沒有區塊,傳回陣列 entry_names;範例(使用 簡單檔案樹

Dir.glob('*') # => ["config.h", "lib", "main.rb"]

如果使用區塊,使用每個 entry_names 呼叫區塊,並傳回 nil

Dir.glob('*') {|entry_name| puts entry_name } # => nil

輸出

config.h
lib
main.rb

如果給定選用的關鍵字參數 flags,其值會修改相符的內容;請見下方。

如果給定選用的關鍵字參數 base,其值會指定基本目錄。每個樣式字串會指定相對於基本目錄的項目;預設值為 '.'。基本目錄不會加到結果中的項目名稱之前

Dir.glob(pattern, base: 'lib').take(5)
# => ["abbrev.gemspec", "abbrev.rb", "base64.gemspec", "base64.rb", "benchmark.gemspec"]
Dir.glob(pattern, base: 'lib/irb').take(5)
# => ["cmd", "color.rb", "color_printer.rb", "completion.rb", "context.rb"]

如果給定選用的關鍵字 sort,其值會指定是否要對陣列進行排序;預設值為 true。使用該關鍵字傳遞值 false 會停用排序(儘管底層檔案系統可能已對陣列進行排序)。

樣式

每個樣式字串會根據特定元字元進行擴充;以下範例使用 Ruby 檔案樹

  • '*':與項目名稱中的任何子字串相符,與正規表示式 /.*/mx 的意義類似;可能會受到樣式字串中其他值的限制

    • '*' 與所有項目名稱相符

      Dir.glob('*').take(3)  # => ["BSDL", "CONTRIBUTING.md", "COPYING"]
      
    • 'c*' 符合以 'c' 開頭的項目名稱

      Dir.glob('c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
      
    • '*c' 符合以 'c' 結尾的項目名稱

      Dir.glob('*c').take(3) # => ["addr2line.c", "array.c", "ast.c"]
      
    • '*c*' 符合包含 'c' 的項目名稱,即使在開頭或結尾

      Dir.glob('*c*').take(3) # => ["CONTRIBUTING.md", "COPYING", "COPYING.ja"]
      

    不符合類 Unix 的隱藏項目名稱(「點文件」)。若要將這些項目名稱包含在符合的項目名稱中,請使用旗標 IO::FNM_DOTMATCH 或類似 '{*,.*}' 的項目。

  • '**':如果後面接著斜線字元 '/',則遞迴符合項目名稱

    Dir.glob('**/').take(3) # => ["basictest/", "benchmark/", "benchmark/gc/"]
    

    如果字串模式包含其他字元或後面未接著斜線字元,則等於 '*'

  • '?' 符合任何單一字元;與正規表示法 /./ 的意義類似

    Dir.glob('io.?') # => ["io.c"]
    
  • '[set]':符合字串 set 中的任何一個字元;行為類似 正規表示法字元類別,包括集合否定('[^a-z]'

    Dir.glob('*.[a-z][a-z]').take(3)
    # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"]
    
  • '{abc,xyz}':符合字串 abc 或字串 xyz;行為類似 正規表示法交替

    Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"]
    

    可以提供兩個以上的選項。

  • \:跳脫後面的後設字元。

    請注意,在 Windows 上,反斜線字元不可用於字串模式:Dir['c:\foo*'] 將無法運作,請改用 Dir['c:/foo*']

更多範例(使用 簡單檔案樹

# We're in the example directory.
File.basename(Dir.pwd) # => "example"
Dir.glob('config.?')              # => ["config.h"]
Dir.glob('*.[a-z][a-z]')          # => ["main.rb"]
Dir.glob('*.[^r]*')               # => ["config.h"]
Dir.glob('*.{rb,h}')              # => ["main.rb", "config.h"]
Dir.glob('*')                     # => ["config.h", "lib", "main.rb"]
Dir.glob('*', File::FNM_DOTMATCH) # => [".", "config.h", "lib", "main.rb"]
Dir.glob(["*.rb", "*.h"])         # => ["main.rb", "config.h"]

Dir.glob('**/*.rb')
=> ["lib/song/karaoke.rb", "lib/song.rb", "main.rb"]

Dir.glob('**/*.rb', base: 'lib')  #   => ["song/karaoke.rb", "song.rb"]

Dir.glob('**/lib')                # => ["lib"]

Dir.glob('**/lib/**/*.rb')        # => ["lib/song/karaoke.rb", "lib/song.rb"]

Dir.glob('**/lib/*.rb')           # => ["lib/song.rb"]

旗標

如果提供選用關鍵字引數 flags(預設為零,無旗標),其值應該是模組 File::Constants 中定義的一個或多個常數的按位元 OR。

範例

flags = File::FNM_EXTGLOB | File::FNM_DOTMATCH

指定旗標可以延伸、限制或以其他方式修改符合條件。

這個方法的旗標(File::Constants 中的其他常數不適用)

  • File::FNM_DOTMATCH:指定應考慮以 '.' 開頭的項目名稱進行符合條件

    Dir.glob('*').take(5)
    # => ["BSDL", "CONTRIBUTING.md", "COPYING", "COPYING.ja", "GPL"]
    Dir.glob('*', flags: File::FNM_DOTMATCH).take(5)
    # => [".", ".appveyor.yml", ".cirrus.yml", ".dir-locals.el", ".document"]
    
  • File::FNM_EXTGLOB:啟用模式延伸 '{a,b}',符合模式 a 和模式 b;行為類似 正規表示法聯集(例如,'(?:a|b)'

    pattern = '{LEGAL,BSDL}'
    Dir.glob(pattern)      # => ["LEGAL", "BSDL"]
    
  • File::FNM_NOESCAPE:指定使用反斜線字元 '\' 跳脫已停用;該字元不是跳脫字元。

  • File::FNM_PATHNAME:指定後設字元 '*''?' 不符合目錄分隔符號。

  • File::FNM_SHORTNAME:指定如果模式存在,則模式可以符合短名稱;僅限 Windows。

# File dir.rb, line 410
def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
  Primitive.dir_s_glob(pattern, flags, base, sort)
end
home(user_name = nil) → dirpath 按一下以切換來源

如果 user_name 不為 nil,則傳回指定使用者的家目錄路徑,否則傳回目前登入使用者

Dir.home         # => "/home/me"
Dir.home('root') # => "/root"

如果 user_name 不是使用者名稱,會引發 ArgumentError

static VALUE
dir_s_home(int argc, VALUE *argv, VALUE obj)
{
    VALUE user;
    const char *u = 0;

    rb_check_arity(argc, 0, 1);
    user = (argc > 0) ? argv[0] : Qnil;
    if (!NIL_P(user)) {
        SafeStringValue(user);
        rb_must_asciicompat(user);
        u = StringValueCStr(user);
        if (*u) {
            return rb_home_dir_of(user, rb_str_new(0, 0));
        }
    }
    return rb_default_home_dir(rb_str_new(0, 0));

}
mkdir(dirpath, permissions = 0775) → 0 按一下以切換來源

dirpath 的底層檔案系統中,使用指定的 permissions 建立目錄;傳回零

Dir.mkdir('foo')
File.stat(Dir.new('foo')).mode.to_s(8)[1..4] # => "0755"
Dir.mkdir('bar', 0644)
File.stat(Dir.new('bar')).mode.to_s(8)[1..4] # => "0644"

請參閱 檔案權限。請注意,Windows 會略過引數 permissions

static VALUE
dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
{
    struct mkdir_arg m;
    VALUE path, vmode;
    int r;

    if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
        m.mode = NUM2MODET(vmode);
    }
    else {
        m.mode = 0777;
    }

    path = check_dirname(path);
    m.path = RSTRING_PTR(path);
    r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0);
    if (r < 0)
        rb_sys_fail_path(path);

    return INT2FIX(0);
}
mktmpdir(prefix_suffix=nil, *rest, **options) { |dup| ... } 按一下以切換來源

Dir.mktmpdir 會建立一個暫時目錄。

目錄會建立為 0700 權限。應用程式不應變更權限,讓其他使用者可以存取暫時目錄。

目錄名稱的前綴字和後綴字會由選用的第一個引數 prefix_suffix 指定。

  • 如果未指定或為 nil,會使用「d」作為前綴字,且不使用後綴字。

  • 如果是一個字串,會使用該字串作為前綴字,且不使用後綴字。

  • 如果是一個陣列,第一個元素會用作前綴字,第二個元素會用作後綴字。

Dir.mktmpdir {|dir| dir is ".../d..." }
Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }

目錄會建立在 Dir.tmpdir 或選用的第二個引數 tmpdir 下,如果給予非 nil 值。

Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }

如果給予區塊,會使用目錄路徑來產生區塊。目錄及其內容會在 Dir.mktmpdir 傳回前,使用 FileUtils.remove_entry 移除。

Dir.mktmpdir {|dir|
  # use the directory...
  open("#{dir}/foo", "w") { something using the file }
}

如果未給予區塊,會傳回目錄路徑。在此情況下,Dir.mktmpdir 不會移除目錄。

dir = Dir.mktmpdir
begin
  # use the directory...
  open("#{dir}/foo", "w") { something using the file }
ensure
  # remove the directory.
  FileUtils.remove_entry dir
end
# File lib/tmpdir.rb, line 91
def self.mktmpdir(prefix_suffix=nil, *rest, **options)
  base = nil
  path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|path, _, _, d|
    base = d
    mkdir(path, 0700)
  }
  if block_given?
    begin
      yield path.dup
    ensure
      unless base
        stat = File.stat(File.dirname(path))
        if stat.world_writable? and !stat.sticky?
          raise ArgumentError, "parent directory is world writable but not sticky"
        end
      end
      FileUtils.remove_entry path
    end
  else
    path
  end
end
new(dirpath) → dir 按一下以切換來源
new(dirpath, encoding: nil) → dir

傳回 dirpath 目錄的新 Dir 物件

Dir.new('.') # => #<Dir:.>

使用選用關鍵字引數 encoding 給予的值,指定目錄項目名稱的編碼;如果為 nil(預設值),會使用檔案系統的編碼

Dir.new('.').read.encoding                       # => #<Encoding:UTF-8>
Dir.new('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
# File dir.rb, line 211
def initialize(name, encoding: nil)
  Primitive.dir_initialize(name, encoding)
end
open(dirpath) → dir 按一下以切換來源
open(dirpath, encoding: nil) → dir
open(dirpath) {|dir| ... } → 物件
open(dirpath, encoding: nil) {|dir| ... } → 物件

dirpath 目錄建立新的 Dir 物件 dir

沒有區塊的話,此方法等同於 Dir.new(dirpath, encoding)

Dir.open('.') # => #<Dir:.>

有提供區塊的話,會呼叫區塊並傳入已建立的 dir;區塊結束時會關閉 dir 並傳回區塊的值

Dir.open('.') {|dir| dir.inspect } # => "#<Dir:.>"

使用選用關鍵字引數 encoding 給予的值,指定目錄項目名稱的編碼;如果為 nil(預設值),會使用檔案系統的編碼

Dir.open('.').read.encoding                       # => #<Encoding:UTF-8>
Dir.open('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
# File dir.rb, line 183
def self.open(name, encoding: nil, &block)
  dir = Primitive.dir_s_open(name, encoding)
  if block
    begin
      yield dir
    ensure
      Primitive.dir_s_close(dir)
    end
  else
    dir
  end
end
pwd → string 按一下以切換來源

傳回目前工作目錄的路徑

Dir.chdir("/tmp") # => 0
Dir.pwd           # => "/tmp"
static VALUE
dir_s_getwd(VALUE dir)
{
    return rb_dir_getwd();
}
rmdir(dirpath) → 0 按一下以切換來源

從底層檔案系統中移除 dirpath 的目錄

Dir.rmdir('foo') # => 0

如果目錄不為空,則引發例外。

static VALUE
dir_s_rmdir(VALUE obj, VALUE dir)
{
    const char *p;
    int r;

    dir = check_dirname(dir);
    p = RSTRING_PTR(dir);
    r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0);
    if (r < 0)
        rb_sys_fail_path(dir);

    return INT2FIX(0);
}
tmpdir() 按一下以切換原始碼

傳回作業系統的暫存檔路徑。

# File lib/tmpdir.rb, line 26
def self.tmpdir
  ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', SYSTMPDIR], ['/tmp']*2, ['.']*2].find do |name, dir|
    unless dir
      next if !(dir = ENV[name] rescue next) or dir.empty?
    end
    dir = File.expand_path(dir)
    stat = File.stat(dir) rescue next
    case
    when !stat.directory?
      warn "#{name} is not a directory: #{dir}"
    when !stat.writable?
      warn "#{name} is not writable: #{dir}"
    when stat.world_writable? && !stat.sticky?
      warn "#{name} is world-writable: #{dir}"
    else
      break dir
    end
  end or raise ArgumentError, "could not find a temporary directory"
end

公開實例方法

chdir → 0 按一下以切換原始碼
chdir { ... } → 物件

將目前工作目錄變更為 self

Dir.pwd # => "/"
dir = Dir.new('example')
dir.chdir
Dir.pwd # => "/example"

有區塊時,暫時變更工作目錄

  • 呼叫區塊。

  • 變更到指定的目錄。

  • 執行區塊(不產生引數)。

  • 還原先前的目錄。

  • 傳回區塊的傳回值。

如果可用的話,會使用 Dir.fchdir;如果不可用,則會使用 Dir.chdir,請參閱這些方法的注意事項。

static VALUE
dir_chdir(VALUE dir)
{
#if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD
    return dir_s_fchdir(rb_cDir, dir_fileno(dir));
#else
    return chdir_path(dir_get(dir)->path, false);
#endif
}
children → 陣列 按一下以切換原始碼

傳回 self 中的項目名稱陣列,但不包含 '.''..'

dir = Dir.new('/example')
dir.children # => ["config.h", "lib", "main.rb"]
static VALUE
dir_collect_children(VALUE dir)
{
    VALUE ary = rb_ary_new();
    dir_each_entry(dir, rb_ary_push, ary, TRUE);
    return ary;
}
close → nil 按一下以切換原始碼

關閉 self 中的串流(如果已開啟),並傳回 nil;如果 self 已關閉,則會忽略

dir = Dir.new('example')
dir.read     # => "."
dir.close     # => nil
dir.close     # => nil
dir.read # Raises IOError.
static VALUE
dir_close(VALUE dir)
{
    struct dir_data *dirp;

    dirp = dir_get(dir);
    if (!dirp->dir) return Qnil;
    closedir(dirp->dir);
    dirp->dir = NULL;

    return Qnil;
}
each {|entry_name| ... } → self 按一下以切換原始碼

呼叫區塊並傳入 self 中的每個項目名稱

Dir.new('example').each {|entry_name| p entry_name }

輸出

"."
".."
"config.h"
"lib"
"main.rb"

如果沒有提供區塊,則會傳回 Enumerator

static VALUE
dir_each(VALUE dir)
{
    RETURN_ENUMERATOR(dir, 0, 0);
    return dir_each_entry(dir, dir_yield, Qnil, FALSE);
}
each_child {|entry_name| ... } → self 按一下以切換原始碼

呼叫區塊並傳入 self 中的每個項目名稱,但不包含 '.''..'

dir = Dir.new('/example')
dir.each_child {|entry_name| p entry_name }

輸出

"config.h"
"lib"
"main.rb"

如果沒有提供區塊,則會傳回列舉器。

static VALUE
dir_each_child_m(VALUE dir)
{
    RETURN_ENUMERATOR(dir, 0, 0);
    return dir_each_entry(dir, dir_yield, Qnil, TRUE);
}
fileno → 整數 按一下以切換原始碼

傳回 dir 中使用的檔案描述子。

d = Dir.new('..')
d.fileno # => 8

此方法使用 POSIX 2008 定義的 dirfd() 函式;此方法未在非 POSIX 平台上實作(會引發 NotImplementedError)。

static VALUE
dir_fileno(VALUE dir)
{
    struct dir_data *dirp;
    int fd;

    GetDIR(dir, dirp);
    fd = dirfd(dirp->dir);
    if (fd == -1)
        rb_sys_fail("dirfd");
    return INT2NUM(fd);
}
inspect → 字串 按一下以切換原始碼

傳回 self 的字串說明

Dir.new('example').inspect # => "#<Dir:example>"
static VALUE
dir_inspect(VALUE dir)
{
    struct dir_data *dirp;

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
    if (!NIL_P(dirp->path)) {
        VALUE str = rb_str_new_cstr("#<");
        rb_str_append(str, rb_class_name(CLASS_OF(dir)));
        rb_str_cat2(str, ":");
        rb_str_append(str, dirp->path);
        rb_str_cat2(str, ">");
        return str;
    }
    return rb_funcallv(dir, idTo_s, 0, 0);
}
path → 字串或 nil 按一下以切換原始碼

傳回用來建立 selfdirpath 字串(或 nil,如果使用 Dir.for_fd 方法建立)

Dir.new('example').path # => "example"
static VALUE
dir_path(VALUE dir)
{
    struct dir_data *dirp;

    TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dirp);
    if (NIL_P(dirp->path)) return Qnil;
    return rb_str_dup(dirp->path);
}
別名為: to_path
pos
別名為:tell
pos = position → 整數 按一下以切換來源

設定 self 中的位置並傳回 positionposition 的值應已從先前呼叫 tell 傳回;若否,則無法指定從後續呼叫 read 傳回的值。

請參閱 Dir As Stream-Like

範例

dir = Dir.new('example')
dir.pos      # => 0
dir.pos = 3  # => 3
dir.pos      # => 3
dir.pos = 30 # => 30
dir.pos      # => 5
static VALUE
dir_set_pos(VALUE dir, VALUE pos)
{
    dir_seek(dir, pos);
    return pos;
}
read → 字串或 nil 按一下以切換來源

self 讀取並傳回下一個輸入名稱;若在串流結尾,則傳回 nil;請參閱 Dir As Stream-Like

dir = Dir.new('example')
dir.read # => "."
dir.read # => ".."
dir.read # => "config.h"
static VALUE
dir_read(VALUE dir)
{
    struct dir_data *dirp;
    struct dirent *dp;

    GetDIR(dir, dirp);
    rb_errno_set(0);
    if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) {
        return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
    }
    else {
        int e = errno;
        if (e != 0) rb_syserr_fail(e, 0);
        return Qnil;            /* end of stream */
    }
}
rewind → self 按一下以切換來源

self 中的位置設定為零;請參閱 Dir As Stream-Like

dir = Dir.new('example')
dir.read    # => "."
dir.read    # => ".."
dir.pos     # => 2
dir.rewind  # => #<Dir:example>
dir.pos     # => 0
static VALUE
dir_rewind(VALUE dir)
{
    struct dir_data *dirp;

    GetDIR(dir, dirp);
    rewinddir(dirp->dir);
    return dir;
}
seek(position) → self 按一下以切換來源

設定 self 中的位置並傳回 selfposition 的值應已從先前呼叫 tell 傳回;若否,則無法指定從後續呼叫 read 傳回的值。

請參閱 Dir As Stream-Like

範例

dir = Dir.new('example')
dir.pos      # => 0
dir.seek(3)  # => #<Dir:example>
dir.pos      # => 3
dir.seek(30) # => #<Dir:example>
dir.pos      # => 5
static VALUE
dir_seek(VALUE dir, VALUE pos)
{
    struct dir_data *dirp;
    long p = NUM2LONG(pos);

    GetDIR(dir, dirp);
    seekdir(dirp->dir, p);
    return dir;
}
tell → 整數 按一下以切換來源

傳回 self 的目前位置;請參閱 Dir As Stream-Like

dir = Dir.new('example')
dir.tell  # => 0
dir.read  # => "."
dir.tell  # => 1
static VALUE
dir_tell(VALUE dir)
{
    struct dir_data *dirp;
    long pos;

    GetDIR(dir, dirp);
    pos = telldir(dirp->dir);
    return rb_int2inum(pos);
}
別名為:pos
to_path
別名為:path