類別 File
File 物件是底層平台中檔案的表示。
類別 File 延伸模組 FileTest
,支援單例方法,例如 File.exist?
。
關於範例¶ ↑
這裡的許多範例使用這些變數
# English text with newlines. text = <<~EOT First line Second line Fourth line Fifth line EOT # Russian text. russian = "\u{442 435 441 442}" # => "тест" # Binary data. data = "\u9990\u9991\u9992\u9993\u9994" # Text file. File.write('t.txt', text) # File with Russian text. File.write('t.rus', russian) # File with binary data. f = File.new('t.dat', 'wb:UTF-16') f.write(data) f.close
存取模式¶ ↑
方法 File.new
和 File.open
各為指定檔案路徑建立一個 File 物件。
字串存取模式¶ ↑
方法 File.new
和 File.open
各可以接受字串引數 mode
,其中
讀取/寫入模式¶ ↑
讀取/寫入 mode
決定
-
檔案是否要先被截斷。
-
是否允許讀取,如果允許
-
檔案中的初始讀取位置。
-
在檔案中的哪些位置可以讀取。
-
-
是否允許寫入,如果允許
-
檔案中的初始寫入位置。
-
在檔案中的哪些位置可以寫入。
-
這些表格摘要
Read/Write Modes for Existing File |------|-----------|----------|----------|----------|-----------| | R/W | Initial | | Initial | | Initial | | Mode | Truncate? | Read | Read Pos | Write | Write Pos | |------|-----------|----------|----------|----------|-----------| | 'r' | No | Anywhere | 0 | Error | - | | 'w' | Yes | Error | - | Anywhere | 0 | | 'a' | No | Error | - | End only | End | | 'r+' | No | Anywhere | 0 | Anywhere | 0 | | 'w+' | Yes | Anywhere | 0 | Anywhere | 0 | | 'a+' | No | Anywhere | End | End only | End | |------|-----------|----------|----------|----------|-----------| Read/Write Modes for \File To Be Created |------|----------|----------|----------|-----------| | R/W | | Initial | | Initial | | Mode | Read | Read Pos | Write | Write Pos | |------|----------|----------|----------|-----------| | 'w' | Error | - | Anywhere | 0 | | 'a' | Error | - | End only | 0 | | 'w+' | Anywhere | 0 | Anywhere | 0 | | 'a+' | Anywhere | 0 | End only | End | |------|----------|----------|----------|-----------|
請注意,對於不存在的檔案,不允許模式 'r'
和 'r+'
(會引發例外狀況)。
在表格中
-
任何位置
表示方法IO#rewind
、IO#pos=
和IO#seek
可以用來變更檔案的位置,因此允許的讀取或寫入可以在檔案中的任何位置進行。 -
錯誤
表示如果嘗試進行不允許的讀取或寫入,就會引發例外狀況。
現有檔案的讀取/寫入模式¶ ↑
-
'r'
:-
File
沒有先被截斷f = File.new('t.txt') # => #<File:t.txt> f.size == 0 # => false
-
檔案的初始讀取位置為 0
f.pos # => 0
-
File
可以從任何位置讀取;請參閱IO#rewind
、IO#pos=
、IO#seek
f.readline # => "First line\n" f.readline # => "Second line\n" f.rewind f.readline # => "First line\n" f.pos = 1 f.readline # => "irst line\n" f.seek(1, :CUR) f.readline # => "econd line\n"
-
不允許寫入
f.write('foo') # Raises IOError.
-
-
'w'
:-
File
先被截斷path = 't.tmp' File.write(path, text) f = File.new(path, 'w') f.size == 0 # => true
-
檔案的初始寫入位置為 0
f.pos # => 0
-
File
可以寫入任何位置(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.write('foo') f.flush File.read(path) # => "foo" f.pos # => 3 f.write('bar') f.flush File.read(path) # => "foobar" f.pos # => 6 f.rewind f.write('baz') f.flush File.read(path) # => "bazbar" f.pos # => 3 f.pos = 3 f.write('foo') f.flush File.read(path) # => "bazfoo" f.pos # => 6 f.seek(-3, :END) f.write('bam') f.flush File.read(path) # => "bazbam" f.pos # => 6 f.pos = 8 f.write('bah') # Zero padding as needed. f.flush File.read(path) # => "bazbam\u0000\u0000bah" f.pos # => 11
-
禁止讀取
f.read # Raises IOError.
-
-
'a'
:-
File
沒有先被截斷path = 't.tmp' File.write(path, 'foo') f = File.new(path, 'a') f.size == 0 # => false
-
檔案的初始位置為 0(但會略過)
f.pos # => 0
-
File
只能寫入檔案結尾;IO#rewind
、IO#pos=
、IO#seek
都不會影響寫入f.write('bar') f.flush File.read(path) # => "foobar" f.write('baz') f.flush File.read(path) # => "foobarbaz" f.rewind f.write('bat') f.flush File.read(path) # => "foobarbazbat"
-
禁止讀取
f.read # Raises IOError.
-
-
'r+'
:-
File
沒有先被截斷path = 't.tmp' File.write(path, text) f = File.new(path, 'r+') f.size == 0 # => false
-
檔案的初始讀取位置為 0
f.pos # => 0
-
File
可以隨意讀寫(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.readline # => "First line\n" f.readline # => "Second line\n" f.rewind f.readline # => "First line\n" f.pos = 1 f.readline # => "irst line\n" f.seek(1, :CUR) f.readline # => "econd line\n" f.rewind f.write('WWW') f.flush File.read(path) # => "WWWst line\nSecond line\nFourth line\nFifth line\n" f.pos = 10 f.write('XXX') f.flush File.read(path) # => "WWWst lineXXXecond line\nFourth line\nFifth line\n" f.seek(-6, :END) # => 0 f.write('YYY') # => 3 f.flush # => #<File:t.tmp> File.read(path) # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n" f.seek(2, :END) f.write('ZZZ') # Zero padding as needed. f.flush File.read(path) # => "WWWst lineXXXecond line\nFourth line\nFifth YYYe\n\u0000\u0000ZZZ"
-
-
'a+'
:-
File
沒有先被截斷path = 't.tmp' File.write(path, 'foo') f = File.new(path, 'a+') f.size == 0 # => false
-
檔案的初始讀取位置為 0
f.pos # => 0
-
File
只能寫入檔案結尾;IO#rewind
、IO#pos=
、IO#seek
都不會影響寫入f.write('bar') f.flush File.read(path) # => "foobar" f.write('baz') f.flush File.read(path) # => "foobarbaz" f.rewind f.write('bat') f.flush File.read(path) # => "foobarbazbat"
-
File
可以從任何位置讀取;請參閱IO#rewind
、IO#pos=
、IO#seek
f.rewind f.read # => "foobarbazbat" f.pos = 3 f.read # => "barbazbat" f.seek(-3, :END) f.read # => "bat"
-
要建立的檔案的讀寫模式¶ ↑
請注意,對於不存在的檔案,不允許模式 'r'
和 'r+'
(會引發例外狀況)。
-
'w'
:-
檔案的初始寫入位置為 0
path = 't.tmp' FileUtils.rm_f(path) f = File.new(path, 'w') f.pos # => 0
-
File
可以寫入任何位置(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.write('foo') f.flush File.read(path) # => "foo" f.pos # => 3 f.write('bar') f.flush File.read(path) # => "foobar" f.pos # => 6 f.rewind f.write('baz') f.flush File.read(path) # => "bazbar" f.pos # => 3 f.pos = 3 f.write('foo') f.flush File.read(path) # => "bazfoo" f.pos # => 6 f.seek(-3, :END) f.write('bam') f.flush File.read(path) # => "bazbam" f.pos # => 6 f.pos = 8 f.write('bah') # Zero padding as needed. f.flush File.read(path) # => "bazbam\u0000\u0000bah" f.pos # => 11
-
禁止讀取
f.read # Raises IOError.
-
-
'a'
:-
檔案的初始寫入位置為 0
path = 't.tmp' FileUtils.rm_f(path) f = File.new(path, 'a') f.pos # => 0
-
寫入只會發生在檔案結尾
f.write('foo') f.pos # => 3 f.write('bar') f.pos # => 6 f.flush File.read(path) # => "foobar" f.rewind f.write('baz') f.flush File.read(path) # => "foobarbaz"
-
禁止讀取
f.read # Raises IOError.
-
-
'w+'
:-
檔案的初始位置為 0
path = 't.tmp' FileUtils.rm_f(path) f = File.new(path, 'w+') f.pos # => 0
-
File
可以寫入任何位置(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.write('foo') f.flush File.read(path) # => "foo" f.pos # => 3 f.write('bar') f.flush File.read(path) # => "foobar" f.pos # => 6 f.rewind f.write('baz') f.flush File.read(path) # => "bazbar" f.pos # => 3 f.pos = 3 f.write('foo') f.flush File.read(path) # => "bazfoo" f.pos # => 6 f.seek(-3, :END) f.write('bam') f.flush File.read(path) # => "bazbam" f.pos # => 6 f.pos = 8 f.write('bah') # Zero padding as needed. f.flush File.read(path) # => "bazbam\u0000\u0000bah" f.pos # => 11
-
File
可以隨意讀取(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.rewind # => 0 f.read # => "bazbam\u0000\u0000bah" f.pos = 3 # => 3 f.read # => "bam\u0000\u0000bah" f.seek(-3, :END) # => 0 f.read # => "bah"
-
-
'a+'
:-
檔案的初始寫入位置為 0
path = 't.tmp' FileUtils.rm_f(path) f = File.new(path, 'a+') f.pos # => 0
-
寫入只會發生在檔案結尾
f.write('foo') f.pos # => 3 f.write('bar') f.pos # => 6 f.flush File.read(path) # => "foobar" f.rewind f.write('baz') f.flush File.read(path) # => "foobarbaz"
-
File
可以隨意讀取(甚至超過檔案結尾);請參閱IO#rewind
、IO#pos=
、IO#seek
f.rewind f.read # => "foobarbaz" f.pos = 3 f.read # => "barbaz" f.seek(-3, :END) f.read # => "baz" f.pos = 800 f.read # => ""
-
資料模式¶ ↑
若要指定資料應視為文字資料或二進位資料,可以將下列任一字串附加到上述任何讀寫模式
-
't'
:文字資料;將預設外部編碼設定為Encoding::UTF_8
;在 Windows 上,啟用 EOL 和 CRLF 之間的轉換,並啟用將0x1A
解釋為檔案結尾標記。 -
'b'
:二進位資料;將預設外部編碼設定為Encoding::ASCII_8BIT
;在 Windows 上,禁止 EOL 和 CRLF 之間的轉換,並停用將0x1A
解釋為檔案結尾標記。
如果兩者都沒有提供,串流預設為文字資料。
範例
File.new('t.txt', 'rt') File.new('t.dat', 'rb')
如果指定資料模式,則不能省略讀寫模式,而且資料模式必須在檔案建立模式(如果有的話)之前
File.new('t.dat', 'b') # Raises an exception. File.new('t.dat', 'rxb') # Raises an exception.
檔案建立模式¶ ↑
可以將下列字串附加到上述任何可寫入字串模式
-
'x'
:如果檔案不存在,則建立檔案;如果檔案存在,則引發例外狀況。
範例
File.new('t.tmp', 'wx')
如果指定檔案建立模式,則不能省略讀寫模式,而且檔案建立模式必須在資料模式之後
File.new('t.dat', 'x') # Raises an exception. File.new('t.dat', 'rxb') # Raises an exception.
整數存取模式¶ ↑
如果模式是整數,則它必須是下列常數中的其中一個或多個,這些常數可以使用按位元 OR 運算子 |
結合
-
File::RDONLY
:僅開放讀取。 -
File::WRONLY
:僅開放寫入。 -
File::RDWR
:開放讀取和寫入。 -
File::APPEND
:僅開放附加。
範例
File.new('t.txt', File::RDONLY) File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
注意:Method
IO#set_encoding
不允許將模式指定為整數。
檔案建立模式指定為整數¶ ↑
這些常數也可以 OR 到整數模式中
-
File::CREAT
:如果檔案不存在,則建立檔案。 -
File::EXCL
:如果給定File::CREAT
且檔案存在,則引發例外狀況。
資料模式指定為整數¶ ↑
資料模式無法指定為整數。當串流存取模式給定為整數時,資料模式永遠是文字,不會是二進位。
請注意,儘管有常數 File::BINARY
,但設定其值在整數串流模式中沒有作用;這是因為,如 File::Constants
中所述,File::BINARY
值會停用換行碼轉換,但不會變更外部編碼。
編碼¶ ↑
上述任何字串模式都可以指定編碼,包括僅外部編碼或外部和內部編碼,方法是附加一個或兩個編碼名稱,並以冒號分隔
f = File.new('t.dat', 'rb') f.external_encoding # => #<Encoding:ASCII-8BIT> f.internal_encoding # => nil f = File.new('t.dat', 'rb:UTF-16') f.external_encoding # => #<Encoding:UTF-16 (dummy)> f.internal_encoding # => nil f = File.new('t.dat', 'rb:UTF-16:UTF-16') f.external_encoding # => #<Encoding:UTF-16 (dummy)> f.internal_encoding # => #<Encoding:UTF-16> f.close
陣列 Encoding.name_list
中提供了許多編碼名稱
Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
設定外部編碼時,讀取的字串會在讀取時標記為該編碼,而寫入的字串會在寫入時轉換為該編碼。
設定外部和內部編碼時,會將讀取的字串從外部編碼轉換為內部編碼,而寫入的字串會從內部編碼轉換為外部編碼。有關轉碼輸入和輸出的更多詳細資訊,請參閱 編碼。
如果外部編碼是 'BOM|UTF-8'
、'BOM|UTF-16LE'
或 'BOM|UTF16-BE'
,Ruby 會檢查輸入文件中的 Unicode BOM 以協助判斷編碼。對於 UTF-16 編碼,檔案開啟模式必須是二進位。如果找到 BOM,則會將其移除,並使用 BOM 中的外部編碼。
請注意,BOM 風格編碼選項不區分大小寫,因此 'bom|utf-8'
也是有效的。
檔案權限¶ ↑
File 物件具有權限,它是一個八進位整數,表示底層平台中實際檔案的權限。
請注意,檔案權限與檔案串流(File 物件)的模式有很大的不同。
在 File 物件中,權限可用於此,其中方法 mode
會傳回權限,儘管其名稱是模式
f = File.new('t.txt') f.lstat.mode.to_s(8) # => "100644"
在基於 Unix 的作業系統中,三個低階八進位數字代表所有者 (6)、群組 (4) 和全世界 (4) 的權限。每個八進位數字中的三元組位元分別代表讀取、寫入和執行權限。
因此,權限 0644
代表所有者的讀寫存取權限,以及群組和全世界的唯讀存取權限。請參閱手冊頁面 open(2) 和 chmod(2)。
對於目錄,執行位元的意義會改變:設定時,可以搜尋目錄。
權限中的高階位元可能表示檔案類型(純文字、目錄、管線、socket 等)和各種其他特殊功能。
在非 Posix 作業系統中,權限可能僅包含唯讀或讀寫,在這種情況下,其餘權限將類似於典型值。例如,在 Windows 中,預設權限為 0644
;唯一可以進行的變更,是將檔案設為唯讀,這會報告為 0444
。
對於實際在底層平台中建立檔案的方法(與僅建立 File 物件相反),可以指定權限
File.new('t.tmp', File::CREAT, 0644) File.new('t.tmp', File::CREAT, 0444)
也可以變更權限
f = File.new('t.tmp', File::CREAT, 0444) f.chmod(0644) f.chmod(0444)
檔案常數¶ ↑
可以在模組 File::Constants
中找到各種常數,以供在 File 和 IO
方法中使用;其名稱陣列由 File::Constants.constants
傳回。
此處內容¶ ↑
首先,其他地方的內容。類別 File
在此,類別 File 提供對下列事項有用的方法
建立¶ ↑
-
::new
:開啟指定路徑的檔案;傳回檔案。 -
::link
:使用硬連結,為現有檔案建立新名稱。 -
::mkfifo
:傳回在指定路徑建立的 FIFO 檔案。 -
::symlink
:為指定的檔案路徑建立符號連結。
查詢¶ ↑
路徑
-
::absolute_path
:傳回給定路徑的絕對檔案路徑。 -
::absolute_path?
:傳回給定路徑是否為絕對檔案路徑。 -
::basename
:傳回給定檔案路徑的最後一個組成部分。 -
::dirname
:傳回給定檔案路徑的所有組成部分,但最後一個組成部分除外。 -
::expand_path
:傳回給定路徑的絕對檔案路徑,並將主目錄的~
擴充。 -
::extname
:傳回給定檔案路徑的副檔名。 -
::fnmatch?
(別名為::fnmatch
):傳回給定檔案路徑是否與給定模式相符。 -
::join
:將路徑組成部分串接成單一的路徑字串。 -
::path
:傳回給定路徑的字串表示。 -
::readlink
:傳回給定符號連結所指向檔案的路徑。 -
::realdirpath
:傳回給定檔案路徑的真實路徑,其中最後一個組成部分不一定要存在。 -
::realpath
:傳回給定檔案路徑的真實路徑,其中所有組成部分都必須存在。 -
::split
:傳回兩個字串的陣列:給定路徑的目錄名稱和檔案基本名稱。
時間
-
::birthtime
:傳回給定檔案建立的Time
。
類型
-
::blockdev?
:傳回給定路徑的檔案是否為區塊裝置。 -
::chardev?
:傳回給定路徑的檔案是否為字元裝置。 -
::directory?
:傳回給定路徑的檔案是否為目錄。 -
::executable?
:傳回給定路徑的檔案是否可由目前程序的有效使用者和群組執行。 -
::executable_real?
:傳回給定路徑的檔案是否可由目前程序的實際使用者和群組執行。 -
::exist?
:傳回給定路徑的檔案是否存在。 -
::file?
:傳回給定路徑的檔案是否為一般檔案。 -
::ftype
:傳回給定路徑的檔案類型字串。 -
::grpowned?
:傳回給定路徑的檔案是否由目前程序的有效群組擁有。 -
::identical?
:傳回兩個給定路徑的檔案是否相同。 -
::lstat
:傳回給定路徑中最後一個符號連結的File::Stat
物件。 -
::owned?
:傳回給定路徑的檔案是否由目前程序的有效使用者擁有。 -
::pipe?
:傳回給定路徑的檔案是否為管線。 -
::readable?
:傳回給定路徑的檔案是否可由目前程序的有效使用者和群組讀取。 -
::readable_real?
:傳回給定路徑的檔案是否可由目前程序的實際使用者和群組讀取。 -
::setgid?
:傳回給定路徑的檔案是否設定了 setgid 位元。 -
::setuid?
:傳回給定路徑檔案的 setuid 位元是否已設定。 -
::socket?
:傳回給定路徑的檔案是否為 socket。 -
::stat
:傳回給定路徑檔案的File::Stat
物件。 -
::sticky?
:傳回給定路徑的檔案是否已設定其 sticky 位元。 -
::symlink?
:傳回給定路徑的檔案是否為符號連結。 -
::umask
:傳回目前程序的 umask 值。 -
::world_readable?
:傳回給定路徑的檔案是否可供其他人讀取。 -
::world_writable?
:傳回給定路徑的檔案是否可供其他人寫入。 -
::writable?
:傳回給定路徑的檔案是否可供目前程序的有效使用者和群組寫入。 -
::writable_real?
:傳回給定路徑的檔案是否可供目前程序的實際使用者和群組寫入。 -
lstat
:傳回self
路徑中最後一個符號連結的File::Stat
物件。
內容
設定¶ ↑
-
::chmod
:變更給定路徑檔案的權限。 -
::chown
:變更給定路徑檔案的所有權。 -
::lchmod
:變更給定路徑中最後一個符號連結的權限。 -
::lchown
:變更給定路徑中最後一個符號連結的所有權。 -
::lutime
:對於每個給定的檔案路徑,設定路徑中最後一個符號連結的存取時間和修改時間。 -
::rename
:將一個給定路徑的檔案移至另一個給定路徑。 -
::utime
:設定給定路徑中每個檔案的存取時間和修改時間。 -
flock
:鎖定或解鎖self
。
其他¶ ↑
-
::truncate
:將給定檔案路徑中的檔案截斷至給定大小。 -
truncate
:將self
截斷至給定大小。
常數
- ALT_SEPARATOR
特定於平台的替代分隔符號
- PATH_SEPARATOR
路徑清單分隔符號
- SEPARATOR
分隔路徑中目錄的部分
- Separator
分隔路徑中目錄的部分
公開類別方法
將路徑名稱轉換為絕對路徑名稱。相對路徑會從程序的目前工作目錄參考,除非給定 dir_string,否則會將其用作起點。如果給定的路徑名稱以「~
」開頭,則不會展開,而是視為一般目錄名稱。
File.absolute_path("~oracle/bin") #=> "<relative_path>/~oracle/bin"
static VALUE s_absolute_path(int c, const VALUE * v, VALUE _) { return rb_file_s_absolute_path(c, v); }
如果 file_name
是絕對路徑,則傳回 true
,否則傳回 false
。
File.absolute_path?("c:/foo") #=> false (on Linux), true (on Windows)
static VALUE s_absolute_path_p(VALUE klass, VALUE fname) { VALUE path = rb_get_path(fname); if (!rb_is_absolute_path(RSTRING_PTR(path))) return Qfalse; return Qtrue; }
將命名檔案的最後存取時間傳回為 Time
物件。
file_name 可以是 IO
物件。
File.atime("testfile") #=> Wed Apr 09 08:51:48 CDT 2003
static VALUE rb_file_s_atime(VALUE klass, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) { int e = errno; FilePathValue(fname); rb_syserr_fail_path(e, fname); } return stat_atime(&st); }
傳回 file_name 中給定的檔案名稱的最後組成部分(在先移除尾隨分隔符號之後),可以使用 File::SEPARATOR
和 File::ALT_SEPARATOR
作為分隔符號來形成,當 File::ALT_SEPARATOR
不為 nil
時。如果給定 suffix,且存在於 file_name 的結尾,則會將其移除。如果 suffix 為「.*」,則會移除任何副檔名。
File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb" File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby" File.basename("/home/gumby/work/ruby.rb", ".*") #=> "ruby"
static VALUE rb_file_s_basename(int argc, VALUE *argv, VALUE _) { VALUE fname, fext, basename; const char *name, *p; long f, n; rb_encoding *enc; fext = Qnil; if (rb_check_arity(argc, 1, 2) == 2) { fext = argv[1]; StringValue(fext); enc = check_path_encoding(fext); } fname = argv[0]; FilePathStringValue(fname); if (NIL_P(fext) || !(enc = rb_enc_compatible(fname, fext))) { enc = rb_enc_get(fname); fext = Qnil; } if ((n = RSTRING_LEN(fname)) == 0 || !*(name = RSTRING_PTR(fname))) return rb_str_new_shared(fname); p = ruby_enc_find_basename(name, &f, &n, enc); if (n >= 0) { if (NIL_P(fext)) { f = n; } else { const char *fp; fp = StringValueCStr(fext); if (!(f = rmext(p, f, n, fp, RSTRING_LEN(fext), enc))) { f = n; } RB_GC_GUARD(fext); } if (f == RSTRING_LEN(fname)) return rb_str_new_shared(fname); } basename = rb_str_new(p, f); rb_enc_copy(basename, fname); return basename; }
傳回命名檔案的建立時間。
file_name 可以是 IO
物件。
File.birthtime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
如果平台沒有建立時間,則會引發 NotImplementedError
。
RUBY_FUNC_EXPORTED VALUE rb_file_s_birthtime(VALUE klass, VALUE fname) { statx_data st; if (rb_statx(fname, &st, STATX_BTIME) < 0) { int e = errno; FilePathValue(fname); rb_syserr_fail_path(e, fname); } return statx_birthtime(&st, fname); }
如果 filepath
指向區塊裝置,則傳回 true
,否則傳回 false
File.blockdev?('/dev/sda1') # => true File.blockdev?(File.new('t.tmp')) # => false
static VALUE rb_file_blockdev_p(VALUE obj, VALUE fname) { #ifndef S_ISBLK # ifdef S_IFBLK # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) # else # define S_ISBLK(m) (0) /* anytime false */ # endif #endif #ifdef S_ISBLK struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (S_ISBLK(st.st_mode)) return Qtrue; #endif return Qfalse; }
如果 filepath
指向字元裝置,則傳回 true
,否則傳回 false
。
File.chardev?($stdin) # => true File.chardev?('t.txt') # => false
static VALUE rb_file_chardev_p(VALUE obj, VALUE fname) { #ifndef S_ISCHR # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (S_ISCHR(st.st_mode)) return Qtrue; return Qfalse; }
將指定檔案的權限位元變更為 mode_int 所代表的位元模式。實際效果取決於作業系統(請參閱本節開頭)。在 Unix 系統上,請參閱 chmod(2)
以取得詳細資料。傳回已處理的檔案數目。
File.chmod(0644, "testfile", "out") #=> 2
static VALUE rb_file_s_chmod(int argc, VALUE *argv, VALUE _) { mode_t mode; apply2args(1); mode = NUM2MODET(*argv++); return apply2files(chmod_internal, argc, argv, &mode); }
將指定檔案的所有者和群組變更為指定的數字所有者和群組 ID。只有具有超級使用者權限的程序才能變更檔案的所有者。檔案的目前所有者可以將檔案的群組變更為所有者所屬的任何群組。忽略 nil
或 -1 的所有者或群組 ID。傳回已處理的檔案數目。
File.chown(nil, 100, "testfile")
static VALUE rb_file_s_chown(int argc, VALUE *argv, VALUE _) { struct chown_args arg; apply2args(2); arg.owner = to_uid(*argv++); arg.group = to_gid(*argv++); return apply2files(chown_internal, argc, argv, &arg); }
傳回指定檔案的變更時間(變更檔案目錄資訊的時間,而非檔案本身)。
file_name 可以是 IO
物件。
請注意,在 Windows (NTFS) 上,會傳回建立時間(誕生時間)。
File.ctime("testfile") #=> Wed Apr 09 08:53:13 CDT 2003
static VALUE rb_file_s_ctime(VALUE klass, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) { int e = errno; FilePathValue(fname); rb_syserr_fail_path(e, fname); } return stat_ctime(&st); }
刪除指定的檔案,傳回作為引數傳遞的名稱數目。發生任何錯誤時,會引發例外狀況。由於基礎實作依賴於 unlink(2)
系統呼叫,因此引發的例外狀況類型取決於其錯誤類型(請參閱 linux.die.net/man/2/unlink),且形式為 e.g. Errno::ENOENT。
另請參閱 Dir::rmdir
。
static VALUE rb_file_s_unlink(int argc, VALUE *argv, VALUE klass) { return apply2files(unlink_internal, argc, argv, 0); }
如果 object
給定字串,則在 path
是通往目錄或通往目錄的符號連結的字串路徑時,傳回 true
;否則傳回 false
File.directory?('.') # => true File.directory?('foo') # => false File.symlink('.', 'dirlink') # => 0 File.directory?('dirlink') # => true File.symlink('t,txt', 'filelink') # => 0 File.directory?('filelink') # => false
引數 path
可以是 IO
物件。
VALUE rb_file_directory_p(VALUE obj, VALUE fname) { #ifndef S_ISDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (S_ISDIR(st.st_mode)) return Qtrue; return Qfalse; }
傳回 file_name 中指定的檔名的所有組成部分,唯最後一個組成部分除外(先移除尾端的區隔符號)。當 File::ALT_SEPARATOR
不為 nil
時,可以使用 File::SEPARATOR
和 File::ALT_SEPARATOR
作為區隔符號來形成檔名。
File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
如果給定 level
,則移除最後 level
個組成部分,而不仅仅只移除一個。
File.dirname("/home/gumby/work/ruby.rb", 2) #=> "/home/gumby" File.dirname("/home/gumby/work/ruby.rb", 4) #=> "/"
static VALUE rb_file_s_dirname(int argc, VALUE *argv, VALUE klass) { int n = 1; if ((argc = rb_check_arity(argc, 1, 2)) > 1) { n = NUM2INT(argv[1]); } return rb_file_dirname_n(argv[0], n); }
如果指定的文件存在且大小為零,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_zero_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; return RBOOL(st.st_size == 0); }
如果指定的文件可由這個程序的有效使用者和群組 ID 執行,則傳回 true
。請參閱 eaccess(3)。
Windows 不支援與讀取權限分開的執行權限。在 Windows 上,只有以 .bat、.cmd、.com 或 .exe 結尾的文件才會被視為可執行。
請注意,即使文件不可由有效使用者/群組執行,某些作業系統層級的安全功能仍可能導致此函數傳回 true。
static VALUE rb_file_executable_p(VALUE obj, VALUE fname) { return RBOOL(rb_eaccess(fname, X_OK) >= 0); }
如果指定的文件可由這個程序的實際使用者和群組 ID 執行,則傳回 true
。請參閱 access(3)。
Windows 不支援與讀取權限分開的執行權限。在 Windows 上,只有以 .bat、.cmd、.com 或 .exe 結尾的文件才會被視為可執行。
請注意,即使文件不可由實際使用者/群組執行,某些作業系統層級的安全功能仍可能導致此函數傳回 true。
static VALUE rb_file_executable_real_p(VALUE obj, VALUE fname) { return RBOOL(rb_access(fname, X_OK) >= 0); }
如果指定的文件存在,則傳回 true
。
file_name 可以是 IO
物件。
「文件存在」表示 stat() 或 fstat() 系統呼叫成功。
static VALUE rb_file_exist_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; return Qtrue; }
將路徑名稱轉換為絕對路徑名稱。除非給定 dir_string
,否則相對路徑會從程序的目前工作目錄參考;如果給定 dir_string
,則會將其用作起始點。給定的路徑名稱可以以「~
」開頭,它會擴充為程序所有者的家目錄(環境變數 HOME
必須設定正確)。「~
user」會擴充為指定使用者的家目錄。
File.expand_path("~oracle/bin") #=> "/home/oracle/bin"
以下是一個使用 dir_string
的簡單範例。
File.expand_path("ruby", "/usr/bin") #=> "/usr/bin/ruby"
以下是一個更複雜的範例,它也會解析父目錄。假設我們在 bin/mygem 中,並想要 lib/mygem.rb 的絕對路徑。
File.expand_path("../../lib/mygem.rb", __FILE__) #=> ".../path/to/project/lib/mygem.rb"
因此,它首先解析 __FILE__ 的父目錄,也就是 bin/,然後前往父目錄,也就是專案的根目錄,並附加 lib/mygem.rb
。
static VALUE s_expand_path(int c, const VALUE * v, VALUE _) { return rb_file_s_expand_path(c, v); }
傳回副檔名(path
中從最後一個句點開始的文件名稱部分)。
如果 path
是點檔,或以句點開頭,則開頭的句點不會被視為副檔名的開頭。
當句點是 path
中的最後一個字元時,也會傳回空字串。
在 Windows 上,尾端的句點會被截斷。
File.extname("test.rb") #=> ".rb" File.extname("a/b/d/test.rb") #=> ".rb" File.extname(".a/b/d/test.rb") #=> ".rb" File.extname("foo.") #=> "" on Windows File.extname("foo.") #=> "." on non-Windows File.extname("test") #=> "" File.extname(".profile") #=> "" File.extname(".profile.sh") #=> ".sh"
static VALUE rb_file_s_extname(VALUE klass, VALUE fname) { const char *name, *e; long len; VALUE extname; FilePathStringValue(fname); name = StringValueCStr(fname); len = RSTRING_LEN(fname); e = ruby_enc_find_extname(name, &len, rb_enc_get(fname)); if (len < 1) return rb_str_new(0, 0); extname = rb_str_subseq(fname, e - name, len); /* keep the dot, too! */ return extname; }
如果指定的 file
存在且為一般檔案,則傳回 true
。
file
可以是 IO
物件。
如果 file
參數是符號連結,它會解析符號連結並使用連結所參考的檔案。
static VALUE rb_file_file_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; return RBOOL(S_ISREG(st.st_mode)); }
如果 path
與 pattern
相符,則傳回 true。這個樣式不是正規表示式;而是遵循類似 shell 檔案名稱萬用字元的規則。它可能包含下列的萬用字元
*
-
與任何檔案相符。可以透過萬用字元中的其他值加以限制。等同於正規表示式中的
/.*/x
。*
-
與所有一般檔案相符
c*
-
與所有以
c
開頭的檔案相符 *c
-
與所有以
c
結尾的檔案相符 *c*
-
與所有包含
c
的檔案相符(包括開頭或結尾)。
若要與隱藏檔案(以
.
開頭)相符,請設定 File::FNM_DOTMATCH 旗標。 **
-
遞迴與目錄或擴充與檔案相符。
?
-
與任何一個字元相符。等同於正規表示式中的
/.{1}/
。 [set]
-
與
set
中的任何一個字元相符。行為與Regexp
中的字元集完全相同,包括集否定([^a-z]
)。 \
-
跳脫下一個萬用字元。
{a,b}
-
如果啟用 File::FNM_EXTGLOB 旗標,則與樣式 a 和樣式 b 相符。行為類似
Regexp
聯集((?:a|b)
)。
flags
是 FNM_XXX
常數的按位元 OR。相同的萬用字元樣式和旗標由 Dir::glob
使用。
範例
File.fnmatch('cat', 'cat') #=> true # match entire string File.fnmatch('cat', 'category') #=> false # only match partial string File.fnmatch('c{at,ub}s', 'cats') #=> false # { } isn't supported by default File.fnmatch('c{at,ub}s', 'cats', File::FNM_EXTGLOB) #=> true # { } is supported on FNM_EXTGLOB File.fnmatch('c?t', 'cat') #=> true # '?' match only 1 character File.fnmatch('c??t', 'cat') #=> false # ditto File.fnmatch('c*', 'cats') #=> true # '*' match 0 or more characters File.fnmatch('c*t', 'c/a/b/t') #=> true # ditto File.fnmatch('ca[a-z]', 'cat') #=> true # inclusive bracket expression File.fnmatch('ca[^t]', 'cat') #=> false # exclusive bracket expression ('^' or '!') File.fnmatch('cat', 'CAT') #=> false # case sensitive File.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) #=> true # case insensitive File.fnmatch('cat', 'CAT', File::FNM_SYSCASE) #=> true or false # depends on the system default File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false # wildcard doesn't match '/' on FNM_PATHNAME File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false # ditto File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false # ditto File.fnmatch('\?', '?') #=> true # escaped wildcard becomes ordinary File.fnmatch('\a', 'a') #=> true # escaped ordinary remains ordinary File.fnmatch('\a', '\a', File::FNM_NOESCAPE) #=> true # FNM_NOESCAPE makes '\' ordinary File.fnmatch('[\?]', '?') #=> true # can escape inside bracket expression File.fnmatch('*', '.profile') #=> false # wildcard doesn't match leading File.fnmatch('*', '.profile', File::FNM_DOTMATCH) #=> true # period by default. File.fnmatch('.*', '.profile') #=> true File.fnmatch('**/*.rb', 'main.rb') #=> false File.fnmatch('**/*.rb', './main.rb') #=> false File.fnmatch('**/*.rb', 'lib/song.rb') #=> true File.fnmatch('**.rb', 'main.rb') #=> true File.fnmatch('**.rb', './main.rb') #=> false File.fnmatch('**.rb', 'lib/song.rb') #=> true File.fnmatch('*', 'dave/.profile') #=> true File.fnmatch('**/foo', 'a/b/c/foo', File::FNM_PATHNAME) #=> true File.fnmatch('**/foo', '/a/b/c/foo', File::FNM_PATHNAME) #=> true File.fnmatch('**/foo', 'c:/a/b/c/foo', File::FNM_PATHNAME) #=> true File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME) #=> false File.fnmatch('**/foo', 'a/.b/c/foo', File::FNM_PATHNAME | File::FNM_DOTMATCH) #=> true
# File dir.rb, line 502 def fnmatch(pattern, path, flags = 0) end
識別命名檔案的類型;回傳字串為「file
」、「directory
」、「characterSpecial
」、「blockSpecial
」、「fifo
」、「link
」、「socket
」或「unknown
」之一。
File.ftype("testfile") #=> "file" File.ftype("/dev/tty") #=> "characterSpecial" File.ftype("/tmp/.X11-unix/X0") #=> "socket"
static VALUE rb_file_s_ftype(VALUE klass, VALUE fname) { struct stat st; FilePathValue(fname); fname = rb_str_encode_ospath(fname); if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) { rb_sys_fail_path(fname); } return rb_file_ftype(&st); }
如果命名檔案存在且呼叫程序的有效群組 ID 為檔案的所有者,則傳回 true
。在 Windows 上傳回 false
。
file_name 可以是 IO
物件。
static VALUE rb_file_grpowned_p(VALUE obj, VALUE fname) { #ifndef _WIN32 struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (rb_group_member(st.st_gid)) return Qtrue; #endif return Qfalse; }
如果命名檔案相同,則傳回 true
。
file_1 和 file_2 可以是 IO
物件。
open("a", "w") {} p File.identical?("a", "a") #=> true p File.identical?("a", "./a") #=> true File.link("a", "b") p File.identical?("a", "b") #=> true File.symlink("a", "c") p File.identical?("a", "c") #=> true open("d", "w") {} p File.identical?("a", "d") #=> false
static VALUE rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2) { #ifndef _WIN32 struct stat st1, st2; if (rb_stat(fname1, &st1) < 0) return Qfalse; if (rb_stat(fname2, &st2) < 0) return Qfalse; if (st1.st_dev != st2.st_dev) return Qfalse; if (st1.st_ino != st2.st_ino) return Qfalse; return Qtrue; #else extern VALUE rb_w32_file_identical_p(VALUE, VALUE); return rb_w32_file_identical_p(fname1, fname2); #endif }
傳回使用「/
」連接字串所形成的新字串。
File.join("usr", "mail", "gumby") #=> "usr/mail/gumby"
static VALUE rb_file_s_join(VALUE klass, VALUE args) { return rb_file_join(args); }
等同於 File::chmod
,但不會追蹤符號連結(因此它會變更與連結關聯的權限,而非連結所參考的檔案)。通常無法使用。
static VALUE rb_file_s_lchmod(int argc, VALUE *argv, VALUE _) { mode_t mode; apply2args(1); mode = NUM2MODET(*argv++); return apply2files(lchmod_internal, argc, argv, &mode); }
等同於 File::chown
,但不會追蹤符號連結(因此它會變更與連結關聯的所有者,而非連結所參考的檔案)。通常無法使用。傳回引數清單中的檔案數量。
static VALUE rb_file_s_lchown(int argc, VALUE *argv, VALUE _) { struct chown_args arg; apply2args(2); arg.owner = to_uid(*argv++); arg.group = to_gid(*argv++); return apply2files(lchown_internal, argc, argv, &arg); }
使用硬連結為現有檔案建立新名稱。如果 new_name 已存在,則不會覆寫它(會引發 SystemCallError
的子類別)。並非所有平台都可用。
File.link("testfile", ".testfile") #=> 0 IO.readlines(".testfile")[0] #=> "This is line one\n"
static VALUE rb_file_s_link(VALUE klass, VALUE from, VALUE to) { FilePathValue(from); FilePathValue(to); from = rb_str_encode_ospath(from); to = rb_str_encode_ospath(to); if (link(StringValueCStr(from), StringValueCStr(to)) < 0) { sys_fail2(from, to); } return INT2FIX(0); }
類似於 File::stat
,但不會追蹤最後一個符號連結;而是傳回連結本身的 File::Stat
物件。
File.symlink('t.txt', 'symlink') File.stat('symlink').size # => 47 File.lstat('symlink').size # => 5
static VALUE rb_file_s_lstat(VALUE klass, VALUE fname) { #ifdef HAVE_LSTAT struct stat st; FilePathValue(fname); fname = rb_str_encode_ospath(fname); if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) { rb_sys_fail_path(fname); } return rb_stat_new(&st); #else return rb_file_s_stat(klass, fname); #endif }
將每個命名檔案的存取和修改時間設定為前兩個引數。如果檔案是符號連結,此方法會對連結本身執行動作,而不是其參照對象;如需反向行為,請參閱 File.utime
。傳回引數清單中檔案名稱的數量。
static VALUE rb_file_s_lutime(int argc, VALUE *argv, VALUE _) { return utime_internal_i(argc, argv, TRUE); }
建立具有名稱 file_name 的 FIFO 特殊檔案。mode 指定 FIFO 的權限。它會以慣常的方式由程序的 umask 修改:已建立檔案的權限為 (mode & ~umask)。
static VALUE rb_file_s_mkfifo(int argc, VALUE *argv, VALUE _) { VALUE path; struct mkfifo_arg ma; ma.mode = 0666; rb_check_arity(argc, 1, 2); if (argc > 1) { ma.mode = NUM2MODET(argv[1]); } path = argv[0]; FilePathValue(path); path = rb_str_encode_ospath(path); ma.path = RSTRING_PTR(path); if (rb_thread_call_without_gvl(nogvl_mkfifo, &ma, RUBY_UBF_IO, 0)) { rb_sys_fail_path(path); } return INT2FIX(0); }
根據指定的 mode
開啟位於指定 path
的檔案;建立並傳回該檔案的新 File
物件。
新的 File
物件為緩衝模式 (或非同步模式),除非 filename
是 tty。請參閱 IO#flush
、IO#fsync
、IO#fdatasync
和 IO#sync=
。
引數 path
必須是有效的檔案路徑
f = File.new('/etc/fstab') f.close f = File.new('t.txt') f.close
選用引數 mode
(預設為 'r') 必須指定有效的模式;請參閱 存取模式
f = File.new('t.tmp', 'w') f.close f = File.new('t.tmp', File::RDONLY) f.close
選用引數 perm
(預設為 0666) 必須指定有效的權限,請參閱 檔案權限
f = File.new('t.tmp', File::CREAT, 0644) f.close f = File.new('t.tmp', File::CREAT, 0444) f.close
選用關鍵字引數 opts
指定
static VALUE rb_file_initialize(int argc, VALUE *argv, VALUE io) { if (RFILE(io)->fptr) { rb_raise(rb_eRuntimeError, "reinitializing File"); } if (0 < argc && argc < 3) { VALUE fd = rb_check_to_int(argv[0]); if (!NIL_P(fd)) { argv[0] = fd; return rb_io_initialize(argc, argv, io); } } rb_open_file(argc, argv, io); return io; }
透過 File.new
建立新的 File
物件,並使用指定的引數。
若未指定區塊,傳回 File
物件。
若指定區塊,呼叫區塊並傳回區塊的值,並傳入 File
物件。
static VALUE rb_io_s_open(int argc, VALUE *argv, VALUE klass) { VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS); if (rb_block_given_p()) { return rb_ensure(rb_yield, io, io_close, io); } return io; }
如果命名檔案存在,且呼叫處理程序的有效使用者識別碼為該檔案的所有者,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_owned_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; return RBOOL(st.st_uid == geteuid()); }
傳回路徑的字串表示形式
File.path(File::NULL) #=> "/dev/null" File.path(Pathname.new("/tmp")) #=> "/tmp"
static VALUE rb_file_s_path(VALUE klass, VALUE fname) { return rb_get_path(fname); }
如果 filepath
指向管線,傳回 true
,否則傳回 false
File.mkfifo('tmp/fifo') File.pipe?('tmp/fifo') # => true File.pipe?('t.txt') # => false
static VALUE rb_file_pipe_p(VALUE obj, VALUE fname) { #ifdef S_IFIFO # ifndef S_ISFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) # endif struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (S_ISFIFO(st.st_mode)) return Qtrue; #endif return Qfalse; }
如果這個處理程序的有效使用者和群組識別碼可以讀取命名檔案,則傳回 true
。請參閱 eaccess(3)。
請注意,某些作業系統層級的安全功能可能會導致傳回 true,即使有效使用者/群組無法讀取檔案。
static VALUE rb_file_readable_p(VALUE obj, VALUE fname) { return RBOOL(rb_eaccess(fname, R_OK) >= 0); }
如果這個處理程序的實際使用者和群組識別碼可以讀取命名檔案,則傳回 true
。請參閱 access(3)。
請注意,某些作業系統層級的安全功能可能會導致傳回 true,即使實際使用者/群組無法讀取檔案。
static VALUE rb_file_readable_real_p(VALUE obj, VALUE fname) { return RBOOL(rb_access(fname, R_OK) >= 0); }
傳回由指定連結所參照的檔案名稱。並非所有平台都提供此功能。
File.symlink("testfile", "link2test") #=> 0 File.readlink("link2test") #=> "testfile"
static VALUE rb_file_s_readlink(VALUE klass, VALUE path) { return rb_readlink(path, rb_filesystem_encoding()); }
傳回實際檔案系統中 pathname 的實際 (絕對) 路徑名稱。實際路徑名稱不包含符號連結或無用的點。
如果指定 dir_string,則使用它作為解釋相對路徑名稱的基礎目錄,而非目前目錄。
實際路徑名稱的最後一個組成部分可能不存在。
static VALUE rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass) { VALUE basedir = (rb_check_arity(argc, 1, 2) > 1) ? argv[1] : Qnil; VALUE path = argv[0]; FilePathValue(path); return rb_realpath_internal(basedir, path, 0); }
傳回實際檔案系統中 pathname 的實際 (絕對) 路徑名稱,不包含符號連結或無用的點。
如果指定 dir_string,則使用它作為解釋相對路徑名稱的基礎目錄,而非目前目錄。
呼叫此方法時,路徑名稱的所有組成部分都必須存在。
static VALUE rb_file_s_realpath(int argc, VALUE *argv, VALUE klass) { VALUE basedir = (rb_check_arity(argc, 1, 2) > 1) ? argv[1] : Qnil; VALUE path = argv[0]; FilePathValue(path); return rb_realpath_internal(basedir, path, 1); }
將給定的檔案重新命名為新的名稱。如果無法重新命名檔案,則會引發 SystemCallError
。
File.rename("afile", "afile.bak") #=> 0
static VALUE rb_file_s_rename(VALUE klass, VALUE from, VALUE to) { struct rename_args ra; VALUE f, t; FilePathValue(from); FilePathValue(to); f = rb_str_encode_ospath(from); t = rb_str_encode_ospath(to); ra.src = StringValueCStr(f); ra.dst = StringValueCStr(t); #if defined __CYGWIN__ errno = 0; #endif if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra, RUBY_UBF_IO, 0) < 0) { int e = errno; #if defined DOSISH switch (e) { case EEXIST: if (chmod(ra.dst, 0666) == 0 && unlink(ra.dst) == 0 && rename(ra.src, ra.dst) == 0) return INT2FIX(0); } #endif syserr_fail2(e, from, to); } return INT2FIX(0); }
如果命名檔案已設定 setgid 位元,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_sgid_p(VALUE obj, VALUE fname) { #ifdef S_ISGID return check3rdbyte(fname, S_ISGID); #else return Qfalse; #endif }
如果命名檔案已設定 setuid 位元,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_suid_p(VALUE obj, VALUE fname) { #ifdef S_ISUID return check3rdbyte(fname, S_ISUID); #else return Qfalse; #endif }
傳回 file_name
的大小。
file_name 可以是 IO
物件。
static VALUE rb_file_s_size(VALUE klass, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) { int e = errno; FilePathValue(fname); rb_syserr_fail_path(e, fname); } return OFFT2NUM(st.st_size); }
如果 file_name
不存在或大小為零,則傳回 nil
;否則傳回檔案的大小。
file_name 可以是 IO
物件。
static VALUE rb_file_size_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qnil; if (st.st_size == 0) return Qnil; return OFFT2NUM(st.st_size); }
如果 filepath
指向 socket,則傳回 true
;否則傳回 false
require 'socket' File.socket?(Socket.new(:INET, :STREAM)) # => true File.socket?(File.new('t.txt')) # => false
static VALUE rb_file_socket_p(VALUE obj, VALUE fname) { #ifndef S_ISSOCK # ifdef _S_ISSOCK # define S_ISSOCK(m) _S_ISSOCK(m) # else # ifdef _S_IFSOCK # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK) # else # ifdef S_IFSOCK # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) # endif # endif # endif #endif #ifdef S_ISSOCK struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; if (S_ISSOCK(st.st_mode)) return Qtrue; #endif return Qfalse; }
將給定的字串分割成目錄和檔案元件,並在兩個元素的陣列中傳回。另請參閱 File::dirname
和 File::basename
。
File.split("/home/gumby/.profile") #=> ["/home/gumby", ".profile"]
static VALUE rb_file_s_split(VALUE klass, VALUE path) { FilePathStringValue(path); /* get rid of converting twice */ return rb_assoc_new(rb_file_dirname(path), rb_file_s_basename(1,&path,Qundef)); }
傳回 filepath
中檔案的 File::Stat
物件(請參閱 File::Stat
)
File.stat('t.txt').class # => File::Stat
static VALUE rb_file_s_stat(VALUE klass, VALUE fname) { struct stat st; FilePathValue(fname); fname = rb_str_encode_ospath(fname); if (stat_without_gvl(RSTRING_PTR(fname), &st) < 0) { rb_sys_fail_path(fname); } return rb_stat_new(&st); }
如果命名檔案已設定 sticky 位元,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_sticky_p(VALUE obj, VALUE fname) { #ifdef S_ISVTX return check3rdbyte(fname, S_ISVTX); #else return Qfalse; #endif }
為現有檔案 old_name 建立稱為 new_name 的符號連結。在不支援符號連結的平台上引發 NotImplemented 例外狀況。
File.symlink("testfile", "link2test") #=> 0
static VALUE rb_file_s_symlink(VALUE klass, VALUE from, VALUE to) { FilePathValue(from); FilePathValue(to); from = rb_str_encode_ospath(from); to = rb_str_encode_ospath(to); if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) { sys_fail2(from, to); } return INT2FIX(0); }
如果 filepath
指向符號連結,則傳回 true
;否則傳回 false
symlink = File.symlink('t.txt', 'symlink') File.symlink?('symlink') # => true File.symlink?('t.txt') # => false
static VALUE rb_file_symlink_p(VALUE obj, VALUE fname) { #ifndef S_ISLNK # ifdef _S_ISLNK # define S_ISLNK(m) _S_ISLNK(m) # else # ifdef _S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK) # else # ifdef S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # endif # endif # endif #endif #ifdef S_ISLNK struct stat st; FilePathValue(fname); fname = rb_str_encode_ospath(fname); if (lstat_without_gvl(StringValueCStr(fname), &st) < 0) return Qfalse; if (S_ISLNK(st.st_mode)) return Qtrue; #endif return Qfalse; }
將檔案 file_name 縮短至長度最多為 integer 位元組。並非所有平台都可用。
f = File.new("out", "w") f.write("1234567890") #=> 10 f.close #=> nil File.truncate("out", 5) #=> 0 File.size("out") #=> 5
static VALUE rb_file_s_truncate(VALUE klass, VALUE path, VALUE len) { struct truncate_arg ta; int r; ta.pos = NUM2OFFT(len); FilePathValue(path); path = rb_str_encode_ospath(path); ta.path = StringValueCStr(path); r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_truncate, &ta, RUBY_UBF_IO, NULL); if (r < 0) rb_sys_fail_path(path); return INT2FIX(0); }
傳回此程序目前的 umask 值。如果提供選用引數,將 umask 設為該值並傳回前一個值。Umask 值會從預設權限中減去,因此 umask 為 0222
會讓檔案對所有人都是唯讀的。
File.umask(0006) #=> 18 File.umask #=> 6
static VALUE rb_file_s_umask(int argc, VALUE *argv, VALUE _) { mode_t omask = 0; switch (argc) { case 0: omask = umask(0); umask(omask); break; case 1: omask = umask(NUM2MODET(argv[0])); break; default: rb_error_arity(argc, 0, 1); } return MODET2NUM(omask); }
刪除指定的檔案,傳回作為引數傳遞的名稱數目。發生任何錯誤時,會引發例外狀況。由於基礎實作依賴於 unlink(2)
系統呼叫,因此引發的例外狀況類型取決於其錯誤類型(請參閱 linux.die.net/man/2/unlink),且形式為 e.g. Errno::ENOENT。
另請參閱 Dir::rmdir
。
static VALUE rb_file_s_unlink(int argc, VALUE *argv, VALUE klass) { return apply2files(unlink_internal, argc, argv, 0); }
將每個命名檔案的存取時間和修改時間設為前兩個引數。如果檔案是符號連結,此方法會作用於其所指涉的檔案,而不是連結本身;如需相反的行為,請參閱 File.lutime
。傳回引數清單中的檔案名稱數目。
static VALUE rb_file_s_utime(int argc, VALUE *argv, VALUE _) { return utime_internal_i(argc, argv, FALSE); }
如果其他人可以讀取 file_name,傳回代表 file_name 檔案權限位元的整數。否則傳回 nil
。位元的意義取決於平台;在 Unix 系統上,請參閱 stat(2)
。
file_name 可以是 IO
物件。
File.world_readable?("/etc/passwd") #=> 420 m = File.world_readable?("/etc/passwd") sprintf("%o", m) #=> "644"
static VALUE rb_file_world_readable_p(VALUE obj, VALUE fname) { #ifdef S_IROTH struct stat st; if (rb_stat(fname, &st) < 0) return Qnil; if ((st.st_mode & (S_IROTH)) == S_IROTH) { return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } #endif return Qnil; }
如果其他人可以寫入 file_name,傳回代表 file_name 檔案權限位元的整數。否則傳回 nil
。位元的意義取決於平台;在 Unix 系統上,請參閱 stat(2)
。
file_name 可以是 IO
物件。
File.world_writable?("/tmp") #=> 511 m = File.world_writable?("/tmp") sprintf("%o", m) #=> "777"
static VALUE rb_file_world_writable_p(VALUE obj, VALUE fname) { #ifdef S_IWOTH struct stat st; if (rb_stat(fname, &st) < 0) return Qnil; if ((st.st_mode & (S_IWOTH)) == S_IWOTH) { return UINT2NUM(st.st_mode & (S_IRUGO|S_IWUGO|S_IXUGO)); } #endif return Qnil; }
如果此程序的有效使用者和群組識別碼可以寫入指定檔案,傳回 true
。請參閱 eaccess(3)。
請注意,某些作業系統層級的安全功能可能會導致此方法傳回 true,即使有效使用者/群組無法寫入檔案。
static VALUE rb_file_writable_p(VALUE obj, VALUE fname) { return RBOOL(rb_eaccess(fname, W_OK) >= 0); }
如果此程序的實際使用者和群組識別碼可以寫入指定檔案,傳回 true
。請參閱 access(3)。
請注意,某些作業系統層級的安全功能可能會導致此方法傳回 true,即使實際使用者/群組無法寫入檔案。
static VALUE rb_file_writable_real_p(VALUE obj, VALUE fname) { return RBOOL(rb_access(fname, W_OK) >= 0); }
如果指定的文件存在且大小為零,則傳回 true
。
file_name 可以是 IO
物件。
static VALUE rb_file_zero_p(VALUE obj, VALUE fname) { struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; return RBOOL(st.st_size == 0); }
公開實例方法
傳回最後存取時間(時間
物件)給 檔案,或如果尚未存取過 檔案,則傳回紀元時間。
File.new("testfile").atime #=> Wed Dec 31 18:00:00 CST 1969
static VALUE rb_file_atime(VALUE obj) { rb_io_t *fptr; struct stat st; GetOpenFile(obj, fptr); if (fstat(fptr->fd, &st) == -1) { rb_sys_fail_path(fptr->pathv); } return stat_atime(&st); }
傳回 檔案 的建立時間。
File.new("testfile").birthtime #=> Wed Apr 09 08:53:14 CDT 2003
如果平台沒有建立時間,則會引發 NotImplementedError
。
static VALUE rb_file_birthtime(VALUE obj) { rb_io_t *fptr; statx_data st; GetOpenFile(obj, fptr); if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) { rb_sys_fail_path(fptr->pathv); } return statx_birthtime(&st, fptr->pathv); }
將 檔案 的權限位元變更為 mode_int 所代表的位元模式。實際的影響取決於平台;在 Unix 系統上,請參閱 chmod(2)
以取得詳細資料。遵循符號連結。另請參閱 File#lchmod。
f = File.new("out", "w"); f.chmod(0644) #=> 0
static VALUE rb_file_chmod(VALUE obj, VALUE vmode) { rb_io_t *fptr; mode_t mode; #if !defined HAVE_FCHMOD || !HAVE_FCHMOD VALUE path; #endif mode = NUM2MODET(vmode); GetOpenFile(obj, fptr); #ifdef HAVE_FCHMOD if (fchmod(fptr->fd, mode) == -1) { if (HAVE_FCHMOD || errno != ENOSYS) rb_sys_fail_path(fptr->pathv); } else { if (!HAVE_FCHMOD) return INT2FIX(0); } #endif #if !defined HAVE_FCHMOD || !HAVE_FCHMOD if (NIL_P(fptr->pathv)) return Qnil; path = rb_str_encode_ospath(fptr->pathv); if (chmod(RSTRING_PTR(path), mode) == -1) rb_sys_fail_path(fptr->pathv); #endif return INT2FIX(0); }
將 檔案 的擁有者和群組變更為指定的數字擁有者和群組 ID。只有具備超級使用者權限的程序才能變更檔案的擁有者。檔案的現有擁有者可以將檔案的群組變更為擁有者所屬的任何群組。會忽略 nil
或 -1 的擁有者或群組 ID。遵循符號連結。另請參閱 File#lchown。
File.new("testfile").chown(502, 1000)
static VALUE rb_file_chown(VALUE obj, VALUE owner, VALUE group) { rb_io_t *fptr; rb_uid_t o; rb_gid_t g; #ifndef HAVE_FCHOWN VALUE path; #endif o = to_uid(owner); g = to_gid(group); GetOpenFile(obj, fptr); #ifndef HAVE_FCHOWN if (NIL_P(fptr->pathv)) return Qnil; path = rb_str_encode_ospath(fptr->pathv); if (chown(RSTRING_PTR(path), o, g) == -1) rb_sys_fail_path(fptr->pathv); #else if (fchown(fptr->fd, o, g) == -1) rb_sys_fail_path(fptr->pathv); #endif return INT2FIX(0); }
傳回 檔案 的變更時間(亦即變更檔案目錄資訊的時間,而非檔案本身)。
請注意,在 Windows (NTFS) 上,會傳回建立時間(誕生時間)。
File.new("testfile").ctime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE rb_file_ctime(VALUE obj) { rb_io_t *fptr; struct stat st; GetOpenFile(obj, fptr); if (fstat(fptr->fd, &st) == -1) { rb_sys_fail_path(fptr->pathv); } return stat_ctime(&st); }
根據指定的 locking_constant
鎖定或解鎖檔案,這是下表中值的按位元 OR。
並非所有平台都可用。
如果指定 File::LOCK_NB
且作業會造成封鎖,則傳回 false
;否則傳回 0
。
鎖定常數 | ||
---|---|---|
常數 | 鎖定 | 效果 |
File::LOCK_EX | 獨佔 | 一次只有一個程序可以對 self 保有獨佔鎖定。 |
File::LOCK_NB | 非封鎖 | 不封鎖;可以使用按位元 OR 運算子 | 與其他 File::LOCK_SH 或 File::LOCK_EX 結合使用。 |
File::LOCK_SH | 共用 | 多個程序可以同時對 self 保有共用鎖定。 |
File::LOCK_UN | 解鎖 | 移除此程序所保有的現有鎖定。 |
範例
# Update a counter using an exclusive lock. # Don't use File::WRONLY because it truncates the file. File.open('counter', File::RDWR | File::CREAT, 0644) do |f| f.flock(File::LOCK_EX) value = f.read.to_i + 1 f.rewind f.write("#{value}\n") f.flush f.truncate(f.pos) end # Read the counter using a shared lock. File.open('counter', 'r') do |f| f.flock(File::LOCK_SH) f.read end
static VALUE rb_file_flock(VALUE obj, VALUE operation) { rb_io_t *fptr; int op[2], op1; struct timeval time; op[1] = op1 = NUM2INT(operation); GetOpenFile(obj, fptr); op[0] = fptr->fd; if (fptr->mode & FMODE_WRITABLE) { rb_io_flush_raw(obj, 0); } while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) { int e = errno; switch (e) { case EAGAIN: case EACCES: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif if (op1 & LOCK_NB) return Qfalse; time.tv_sec = 0; time.tv_usec = 100 * 1000; /* 0.1 sec */ rb_thread_wait_for(time); rb_io_check_closed(fptr); continue; case EINTR: #if defined(ERESTART) case ERESTART: #endif break; default: rb_syserr_fail_path(e, fptr->pathv); } } return INT2FIX(0); }
類似於 File#stat
,但不會遵循最後一個符號連結;而是傳回連結本身的 File::Stat
物件
File.symlink('t.txt', 'symlink') f = File.new('symlink') f.stat.size # => 47 f.lstat.size # => 11
static VALUE rb_file_lstat(VALUE obj) { #ifdef HAVE_LSTAT rb_io_t *fptr; struct stat st; VALUE path; GetOpenFile(obj, fptr); if (NIL_P(fptr->pathv)) return Qnil; path = rb_str_encode_ospath(fptr->pathv); if (lstat_without_gvl(RSTRING_PTR(path), &st) == -1) { rb_sys_fail_path(fptr->pathv); } return rb_stat_new(&st); #else return rb_io_stat(obj); #endif }
傳回 檔案 的修改時間。
File.new("testfile").mtime #=> Wed Apr 09 08:53:14 CDT 2003
static VALUE rb_file_mtime(VALUE obj) { rb_io_t *fptr; struct stat st; GetOpenFile(obj, fptr); if (fstat(fptr->fd, &st) == -1) { rb_sys_fail_path(fptr->pathv); } return stat_mtime(&st); }
傳回以位元組為單位的檔案大小。
File.new("testfile").size #=> 66
static VALUE file_size(VALUE self) { return OFFT2NUM(rb_file_size(self)); }
將檔案截斷為最多整數位元組。檔案必須開啟為寫入模式。並非所有平台都支援。
f = File.new("out", "w") f.syswrite("1234567890") #=> 10 f.truncate(5) #=> 0 f.close() #=> nil File.size("out") #=> 5
static VALUE rb_file_truncate(VALUE obj, VALUE len) { rb_io_t *fptr; struct ftruncate_arg fa; fa.pos = NUM2OFFT(len); GetOpenFile(obj, fptr); if (!(fptr->mode & FMODE_WRITABLE)) { rb_raise(rb_eIOError, "not opened for writing"); } rb_io_flush_raw(obj, 0); fa.fd = fptr->fd; if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) { rb_sys_fail_path(fptr->pathv); } return INT2FIX(0); }