類別 Dir
類別 Dir 的物件表示底層檔案系統中的目錄。
它主要包含
-
字串 路徑,在建立物件時提供,用來指定底層檔案系統中的目錄;方法
path
會傳回路徑。 -
字串 項目名稱 的集合,每個名稱都是底層檔案系統中目錄或檔案的名稱;項目名稱可以用 陣列類似方式 或 串流類似方式 擷取。
關於範例¶ ↑
此頁面上的部分範例使用這個簡單的檔案樹
example/ ├── config.h ├── lib/ │ ├── song/ │ │ └── karaoke.rb │ └── song.rb └── main.rb
其他範例使用 Ruby 專案本身 的檔案樹。
Dir 作為陣列類似物件¶ ↑
Dir 物件在某些方面類似陣列
-
它有實例方法
children
、each
和each_child
。 -
它包含 模組 Enumerable。
Dir 作為串流類似物件¶ ↑
Dir 物件在某些方面類似串流。
串流最初開啟供讀取,但可以手動關閉(使用 close
方法),如果串流是由帶有區塊的 Dir.open
建立的,則會在區塊結束時關閉。已關閉的串流不能再進一步處理,也不能重新開啟。
串流有一個 位置,它是目錄中項目的索引
-
初始位置為零(在第一個項目之前)。
-
方法
pos=
會設定位置(但會略過串流外的值),並傳回位置。 -
方法
read
,如果未到串流尾端,會讀取下一個項目並增加位置;如果在串流尾端,則不會增加位置。 -
方法
rewind
將位置設定為零。
範例(使用 簡單檔案樹)
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
-
繼承自 類別 Object。
-
包含 模組 Enumerable,提供數十種其他方法。
在此,類別 Dir 提供對下列項目有用的方法
讀取¶ ↑
-
close
:關閉self
的目錄串流。 -
pos=
:設定self
目錄串流中的位置。 -
read
:讀取並傳回self
目錄串流中的下一個項目。 -
rewind
:將self
目錄串流中的位置設定為第一個項目。 -
seek
:將self
目錄串流中的位置設定為給定偏移量的項目。
設定¶ ↑
查詢¶ ↑
-
::children
:傳回給定目錄的子目錄(檔案和目錄)名稱陣列,但不包含.
或..
。 -
::empty?
:傳回給定路徑是否為空目錄。 -
::entries
:傳回給定目錄的子目錄(檔案和目錄)名稱陣列,包含.
和..
。 -
::exist?
:傳回給定路徑是否為目錄。 -
::getwd
(別名為 pwd):傳回目前工作目錄的路徑。 -
::glob
:傳回與給定模式和旗標相符的檔案路徑陣列。 -
::home
:傳回給定使用者或目前使用者的家目錄路徑。 -
children
:傳回self
的子項(檔案和目錄)名稱陣列,但不包含.
或..
。 -
fileno
:傳回self
的整數檔案描述符。
反覆運算¶ ↑
-
::each_child
:呼叫給定的區塊,並提供給定目錄中的每個項目,但不包含.
或..
。 -
::foreach
:呼叫給定的區塊,並提供給定目錄中的每個項目,包含.
和..
。 -
each
:呼叫給定的區塊,並提供self
中的每個項目,包含.
和..
。 -
each_child
:呼叫給定的區塊,並提供self
中的每個項目,但不包含.
或..
。
其他¶ ↑
常數
- SYSTMPDIR
系統範圍的暫時目錄路徑
公開類別方法
呼叫 Dir.glob
,並提供參數 patterns
以及關鍵字參數 base
和 sort
的值;傳回所選項目名稱的陣列。
# File dir.rb, line 222 def self.[](*args, base: nil, sort: true) Primitive.dir_s_aref(args, base, sort) end
變更目前工作目錄。
有參數 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); }
傳回 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); }
將呼叫程式的根目錄變更為 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); }
從底層檔案系統中移除 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); }
與 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; }
傳回 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; }
傳回 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); }
傳回 dirpath
是否為底層檔案系統中的目錄
Dir.exist?('/example') # => true Dir.exist?('/nosuch') # => false Dir.exist?('/example/main.rb') # => false
與 File.directory?
相同。
VALUE rb_file_directory_p(void) { }
將目前工作目錄變更為整數檔案描述符 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); }
傳回新的 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; }
使用 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; }
傳回目前工作目錄的路徑
Dir.chdir("/tmp") # => 0 Dir.pwd # => "/tmp"
static VALUE dir_s_getwd(VALUE dir) { return rb_dir_getwd(); }
形成一個陣列 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
如果 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)); }
在 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); }
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
傳回 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
為 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
傳回目前工作目錄的路徑
Dir.chdir("/tmp") # => 0 Dir.pwd # => "/tmp"
static VALUE dir_s_getwd(VALUE dir) { return rb_dir_getwd(); }
從底層檔案系統中移除 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); }
傳回作業系統的暫存檔路徑。
# 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
從底層檔案系統中移除 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); }
公開實例方法
將目前工作目錄變更為 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 }
傳回 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; }
關閉 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; }
呼叫區塊並傳入 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); }
呼叫區塊並傳入 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); }
傳回 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); }
傳回 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); }
傳回用來建立 self
的 dirpath
字串(或 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); }
設定 self
中的位置並傳回 position
。position
的值應已從先前呼叫 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; }
從 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 */ } }
將 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; }
設定 self
中的位置並傳回 self
。position
的值應已從先前呼叫 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; }
傳回 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); }