@@ -34,6 +34,36 @@ class File < IO::FileDescriptor
34
34
35
35
getter path : String
36
36
37
+ # Returns a `File::Stat` object for the file given by *path* or returns `nil`
38
+ # if the file does not exist. Raises `Errno` in case of an error. In case of
39
+ # a symbolic link it is followed and information about the target is returned.
40
+ #
41
+ # ```
42
+ # File.write("foo", "foo")
43
+ # File.stat?("foo").try(&.size) # => 3
44
+ # File.stat?("non_existent") # => nil
45
+ # ```
46
+ def self.stat ?(path : String ) : Stat ?
47
+ Crystal ::System ::File .stat?(path)
48
+ end
49
+
50
+ # Returns a `File::Stat` object for the file given by *path* or returns `nil`
51
+ # if the file does not exist. Raises `Errno` in case of an error. In case of
52
+ # a symbolic link information about the link itself is returned.
53
+ #
54
+ # ```
55
+ # File.write("foo", "foo")
56
+ # File.lstat?("foo").try(&.size) # => 3
57
+ #
58
+ # File.symlink("foo", "bar")
59
+ # File.lstat?("bar").try(&.symlink?) # => true
60
+ #
61
+ # File.lstat?("non_existent") # => nil
62
+ # ```
63
+ def self.lstat ?(path : String ) : Stat ?
64
+ Crystal ::System ::File .lstat?(path)
65
+ end
66
+
37
67
# Returns a `File::Stat` object for the file given by *path* or raises
38
68
# `Errno` in case of an error. In case of a symbolic link
39
69
# it is followed and information about the target is returned.
@@ -44,20 +74,20 @@ class File < IO::FileDescriptor
44
74
# File.stat("foo").mtime # => 2015-09-23 06:24:19 UTC
45
75
# ```
46
76
def self.stat (path ) : Stat
47
- Crystal :: System :: File . stat(path)
77
+ stat? (path) || raise Errno .new( " Unable to get stat for #{ path.inspect } " )
48
78
end
49
79
50
80
# Returns a `File::Stat` object for the file given by *path* or raises
51
81
# `Errno` in case of an error. In case of a symbolic link
52
- # information about it is returned.
82
+ # information about the link itself is returned.
53
83
#
54
84
# ```
55
85
# File.write("foo", "foo")
56
86
# File.lstat("foo").size # => 3
57
87
# File.lstat("foo").mtime # => 2015-09-23 06:24:19 UTC
58
88
# ```
59
89
def self.lstat (path ) : Stat
60
- Crystal :: System :: File . lstat(path)
90
+ lstat? (path) || raise Errno .new( " Unable to get stat for #{ path.inspect } " )
61
91
end
62
92
63
93
# Returns `true` if *path* exists else returns `false`
@@ -72,6 +102,20 @@ class File < IO::FileDescriptor
72
102
Crystal ::System ::File .exists?(path)
73
103
end
74
104
105
+ # Returns the size of *filename* bytes. Raises `Errno` if the file at *path*
106
+ # does not exist.
107
+ #
108
+ # ```
109
+ # File.size("foo") # raises Errno
110
+ # File.write("foo", "foo")
111
+ # File.size("foo") # => 3
112
+ # ```
113
+ def self.size (filename ) : UInt64
114
+ stat(filename).size
115
+ rescue ex : Errno
116
+ raise Errno .new(" Error determining size of #{ filename.inspect } " , ex.errno)
117
+ end
118
+
75
119
# Returns `true` if the file at *path* is empty, otherwise returns `false`.
76
120
# Raises `Errno` if the file at *path* does not exist.
77
121
#
@@ -82,7 +126,7 @@ class File < IO::FileDescriptor
82
126
# File.empty?("foo") # => false
83
127
# ```
84
128
def self.empty ?(path) : Bool
85
- Crystal :: System :: File .empty? (path)
129
+ size (path) == 0
86
130
end
87
131
88
132
# Returns `true` if *path* is readable by the real user id of this process else returns `false`.
@@ -125,7 +169,11 @@ class File < IO::FileDescriptor
125
169
# File.file?("foobar") # => false
126
170
# ```
127
171
def self.file ?(path) : Bool
128
- Crystal ::System ::File .file?(path)
172
+ if stat = stat?(path)
173
+ stat.file?
174
+ else
175
+ false
176
+ end
129
177
end
130
178
131
179
# Returns `true` if the given *path* exists and is a directory.
@@ -527,7 +575,11 @@ class File < IO::FileDescriptor
527
575
528
576
# Returns `true` if the *path* is a symbolic link.
529
577
def self.symlink ?(path) : Bool
530
- Crystal ::System ::File .symlink?(path)
578
+ if stat = lstat?(path)
579
+ stat.symlink?
580
+ else
581
+ false
582
+ end
531
583
end
532
584
533
585
# Opens the file named by *filename*. If a file is being created, its initial
@@ -677,11 +729,6 @@ class File < IO::FileDescriptor
677
729
end
678
730
end
679
731
680
- # Returns the size of *filename* bytes.
681
- def self.size (filename ) : UInt64
682
- stat(filename.check_no_null_byte).size
683
- end
684
-
685
732
# Moves *old_filename* to *new_filename*.
686
733
#
687
734
# ```
0 commit comments