recls-ruby 2.12.0 → 2.12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +27 -24
- data/README.md +242 -1
- data/examples/find_files_and_directories.md +33 -30
- data/examples/find_files_and_directories.recursive.md +255 -254
- data/examples/show_hidden_files.md +4 -1
- data/examples/show_hidden_files.rb +1 -1
- data/examples/show_readonly_files.md +4 -1
- data/examples/show_readonly_files.rb +1 -1
- data/lib/recls/api.rb +76 -73
- data/lib/recls/combine_paths_1.rb +26 -23
- data/lib/recls/combine_paths_2plus.rb +32 -29
- data/lib/recls/entry.rb +277 -273
- data/lib/recls/file_search.rb +194 -193
- data/lib/recls/flags.rb +48 -45
- data/lib/recls/foreach.rb +105 -98
- data/lib/recls/obsolete.rb +85 -79
- data/lib/recls/recls.rb +19 -24
- data/lib/recls/stat.rb +137 -134
- data/lib/recls/util.rb +95 -92
- data/lib/recls/version.rb +22 -17
- data/lib/recls/ximpl/os.rb +49 -48
- data/lib/recls/ximpl/unix.rb +41 -38
- data/lib/recls/ximpl/util.rb +600 -599
- data/lib/recls/ximpl/windows.rb +142 -139
- data/lib/recls.rb +10 -9
- data/test/scratch/test_display_parts.rb +33 -33
- data/test/scratch/test_entry.rb +6 -6
- data/test/scratch/test_files_and_directories.rb +8 -8
- data/test/scratch/test_foreach.rb +10 -10
- data/test/scratch/test_module_function.rb +33 -33
- data/test/scratch/test_pattern_arrays.rb +5 -5
- data/test/scratch/test_show_dev_and_ino.rb +1 -1
- data/test/scratch/test_show_hidden.rb +3 -3
- data/test/unit/tc_recls_entries.rb +31 -31
- data/test/unit/tc_recls_entry.rb +19 -19
- data/test/unit/tc_recls_file_search.rb +32 -32
- data/test/unit/tc_recls_module.rb +25 -25
- data/test/unit/tc_recls_util.rb +161 -161
- data/test/unit/tc_recls_ximpl_util.rb +676 -676
- data/test/unit/test_all_separately.sh +1 -1
- data/test/unit/ts_all.rb +4 -4
- metadata +7 -7
data/lib/recls/entry.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#
|
2
|
-
# File:
|
1
|
+
# ######################################################################## #
|
2
|
+
# File: recls/entry.rb
|
3
3
|
#
|
4
|
-
# Purpose:
|
4
|
+
# Purpose: Defines the Recls::Entry class for the recls.Ruby library.
|
5
5
|
#
|
6
|
-
# Created:
|
7
|
-
# Updated:
|
6
|
+
# Created: 24th July 2012
|
7
|
+
# Updated: 20th April 2024
|
8
8
|
#
|
9
|
-
# Author:
|
9
|
+
# Author: Matthew Wilson
|
10
10
|
#
|
11
|
-
# Copyright (c) 2019-
|
11
|
+
# Copyright (c) 2019-2024, Matthew Wilson and Synesis Information Systems
|
12
12
|
# Copyright (c) 2012-2019, Matthew Wilson and Synesis Software
|
13
13
|
# All rights reserved.
|
14
14
|
#
|
@@ -34,7 +34,7 @@
|
|
34
34
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
35
35
|
# POSSIBILITY OF SUCH DAMAGE.
|
36
36
|
#
|
37
|
-
#
|
37
|
+
# ######################################################################## #
|
38
38
|
|
39
39
|
|
40
40
|
require 'recls/ximpl/os'
|
@@ -42,357 +42,361 @@ require 'recls/ximpl/' + (Recls::Ximpl::OS::OS_IS_WINDOWS ? 'windows' : 'unix')
|
|
42
42
|
require 'recls/ximpl/util'
|
43
43
|
require 'recls/flags'
|
44
44
|
|
45
|
+
|
45
46
|
=begin
|
46
47
|
=end
|
47
48
|
|
49
|
+
# @!visibility private
|
48
50
|
class Object; end # :nodoc:
|
49
51
|
|
50
52
|
module Recls
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
54
|
+
# A file-system entry
|
55
|
+
class Entry
|
56
|
+
|
57
|
+
private
|
58
|
+
# @!visibility private
|
59
|
+
def self.get_compare_path_(path)
|
60
|
+
return path.upcase if Recls::Ximpl::OS::OS_IS_WINDOWS
|
61
|
+
path
|
62
|
+
end
|
63
|
+
public
|
64
|
+
|
65
|
+
# initialises an entry instance from the given path,
|
66
|
+
# file_stat, and search_dir
|
67
|
+
def initialize(path, file_stat, search_dir, flags)
|
68
|
+
|
69
|
+
@file_stat = file_stat
|
70
|
+
|
71
|
+
@path = Recls::Ximpl.absolute_path path
|
72
|
+
@short_path = nil
|
73
|
+
@compare_path = Entry.get_compare_path_ @path
|
74
|
+
@hash = @compare_path.hash
|
75
|
+
|
76
|
+
windows_drive, directory, basename, file_name, file_ext = Recls::Ximpl::Util.split_path @path
|
77
|
+
|
78
|
+
@drive = windows_drive
|
79
|
+
@directory_path = "#{windows_drive}#{directory}"
|
80
|
+
@directory = directory ? directory : ''
|
81
|
+
@directory_parts = Recls::Ximpl.directory_parts_from_directory directory
|
82
|
+
@file_full_name = basename ? basename : ''
|
83
|
+
@file_short_name = nil
|
84
|
+
@file_name_only = file_name ? file_name : ''
|
85
|
+
@file_extension = file_ext ? file_ext : ''
|
86
|
+
|
87
|
+
@search_directory = search_dir
|
88
|
+
@search_relative_path = Recls::Ximpl.derive_relative_path search_dir, @path
|
89
|
+
@search_relative_directory_path = Recls::Ximpl.derive_relative_path search_dir, @directory_path
|
90
|
+
@search_relative_directory = @search_relative_directory_path
|
91
|
+
@search_relative_directory_parts = Recls::Ximpl.directory_parts_from_directory @search_relative_directory
|
92
|
+
|
93
|
+
if 0 != (Recls::MARK_DIRECTORIES & flags) && directory?
|
94
|
+
@path = Recls::Ximpl::Util.append_trailing_slash @path
|
95
|
+
@search_relative_path = Recls::Ximpl::Util.append_trailing_slash @search_relative_path
|
96
|
+
end
|
97
|
+
|
98
|
+
@dev = @file_stat.dev if @file_stat
|
99
|
+
@ino = @file_stat.ino if @file_stat
|
100
|
+
@nlink = @file_stat.nlink if @file_stat
|
101
|
+
|
102
|
+
if Recls::Ximpl::OS::OS_IS_WINDOWS && @file_stat
|
103
|
+
|
104
|
+
@dev = @file_stat.by_handle_information.volume_id
|
105
|
+
@ino = @file_stat.by_handle_information.file_index
|
106
|
+
@nlink = @file_stat.by_handle_information.num_links
|
107
|
+
@short_path = @file_stat.short_path
|
108
|
+
@file_short_name = Recls::Ximpl::Util.split_path(@short_path)[2]
|
109
|
+
else
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# ##########################
|
114
|
+
# Name-related attributes
|
115
|
+
|
116
|
+
# (+String+) A normalised form of #path that can be used in comparisons
|
117
|
+
attr_reader :compare_path
|
118
|
+
|
119
|
+
# (+String+) The full-path of the instance
|
120
|
+
attr_reader :path
|
121
|
+
# (+String+) The (Windows) short-form of #path, or +nil+ if not on Windows
|
122
|
+
attr_reader :short_path
|
123
|
+
# (+String+) The (Windows) drive. +nil+ if does not exist
|
124
|
+
attr_reader :drive
|
125
|
+
# (+String+) The full path of the entry's directory (taking into account the
|
126
|
+
# #drive if on Windows)
|
127
|
+
attr_reader :directory_path
|
128
|
+
alias_method :dirname, :directory_path
|
129
|
+
# (+String+) The entry's directory (excluding the #drive if on Windows)
|
130
|
+
attr_reader :directory
|
131
|
+
# (+[ String ]+) An array of directory parts, where each part ends in Recls::PATH_NAME_SEPARATOR
|
132
|
+
attr_reader :directory_parts
|
133
|
+
# (+String+) The entry's file name (combination of #stem + #extension)
|
134
|
+
attr_reader :file_full_name
|
135
|
+
# (+String+) The (Windows) short-form of #basename, or +nil+ if not on Windows
|
136
|
+
attr_reader :file_short_name
|
137
|
+
alias_method :basename, :file_full_name
|
138
|
+
# (+String+) The entry's file stem
|
139
|
+
attr_reader :file_name_only
|
140
|
+
alias_method :stem, :file_name_only
|
141
|
+
# (+String+) The entry's file extension
|
142
|
+
attr_reader :file_extension
|
143
|
+
alias_method :extension, :file_extension
|
144
|
+
# (+String+) The search directory if specified; +nil+ otherwise
|
145
|
+
attr_reader :search_directory
|
146
|
+
# (+String+) The #path relative to #search_directory; +nil+ if no search directory specified
|
147
|
+
attr_reader :search_relative_path
|
148
|
+
# (+String+) The #directory relative to #search_directory; +nil+ if no search directory specified
|
149
|
+
attr_reader :search_relative_directory
|
150
|
+
# (+String+) The #directory_path relative to #search_directory; +nil+ if no search directory specified
|
151
|
+
attr_reader :search_relative_directory_path
|
152
|
+
# (+[ String ]+) The #directory_parts relative to #search_directory; +nil+ if no search directory specified
|
153
|
+
attr_reader :search_relative_directory_parts
|
154
|
+
|
155
|
+
# ##########################
|
156
|
+
# Nature attributes
|
157
|
+
|
158
|
+
# indicates whether the given entry existed at the time the entry
|
159
|
+
# instance was created
|
160
|
+
def exist?
|
161
|
+
|
162
|
+
return false if @file_stat.nil?
|
152
163
|
|
153
|
-
|
154
|
-
|
164
|
+
not @file_stat.nil?
|
165
|
+
end
|
155
166
|
|
156
|
-
|
157
|
-
|
158
|
-
def exist?
|
167
|
+
# indicates whether the given entry is hidden
|
168
|
+
def hidden?
|
159
169
|
|
160
|
-
|
170
|
+
return false if @file_stat.nil?
|
161
171
|
|
162
|
-
|
163
|
-
|
172
|
+
@file_stat.hidden?
|
173
|
+
end
|
164
174
|
|
165
|
-
|
166
|
-
|
175
|
+
# indicates whether the given entry is readonly
|
176
|
+
def readonly?
|
167
177
|
|
168
|
-
|
178
|
+
return false if @file_stat.nil?
|
169
179
|
|
170
|
-
|
171
|
-
|
180
|
+
not @file_stat.writable?
|
181
|
+
end
|
172
182
|
|
173
|
-
|
174
|
-
def readonly?
|
183
|
+
if Recls::Ximpl::OS::OS_IS_WINDOWS
|
175
184
|
|
176
|
-
|
185
|
+
# [WINDOWS-ONLY] Indicates whether the entry has the *system* bit
|
186
|
+
def system?
|
177
187
|
|
178
|
-
|
179
|
-
end
|
188
|
+
return false if @file_stat.nil?
|
180
189
|
|
181
|
-
|
182
|
-
|
190
|
+
@file_stat.system?
|
191
|
+
end
|
183
192
|
|
184
|
-
|
193
|
+
# [WINDOWS-ONLY] Indicates whether the entry has the *archive* bit
|
194
|
+
def archive?
|
185
195
|
|
186
|
-
|
187
|
-
def system?
|
196
|
+
return false if @file_stat.nil?
|
188
197
|
|
189
|
-
|
198
|
+
@file_stat.archive?
|
199
|
+
end
|
190
200
|
|
191
|
-
|
192
|
-
|
201
|
+
# [WINDOWS-ONLY] Indicates whether the entry is a device
|
202
|
+
def device?
|
193
203
|
|
194
|
-
|
195
|
-
def archive?
|
204
|
+
return false if @file_stat.nil?
|
196
205
|
|
197
|
-
|
206
|
+
@file_stat.device?
|
207
|
+
end
|
198
208
|
|
199
|
-
|
200
|
-
|
209
|
+
# [WINDOWS-ONLY] Indicates whether the entry is *normal*
|
210
|
+
def normal?
|
201
211
|
|
202
|
-
|
203
|
-
def device?
|
212
|
+
return false if @file_stat.nil?
|
204
213
|
|
205
|
-
|
214
|
+
@file_stat.normal?
|
215
|
+
end
|
206
216
|
|
207
|
-
|
208
|
-
|
217
|
+
# [WINDOWS-ONLY] Indicates whether the entry has the *temporary* bit
|
218
|
+
def temporary?
|
209
219
|
|
210
|
-
|
211
|
-
def normal?
|
220
|
+
return false if @file_stat.nil?
|
212
221
|
|
213
|
-
|
222
|
+
@file_stat.temporary?
|
223
|
+
end
|
214
224
|
|
215
|
-
|
216
|
-
|
225
|
+
# [WINDOWS-ONLY] Indicates whether the entry has the *compressed* bit
|
226
|
+
def compressed?
|
217
227
|
|
218
|
-
|
219
|
-
def temporary?
|
228
|
+
return false if @file_stat.nil?
|
220
229
|
|
221
|
-
|
230
|
+
@file_stat.compressed?
|
231
|
+
end
|
222
232
|
|
223
|
-
|
224
|
-
|
233
|
+
# [WINDOWS-ONLY] Indicates whether the entry has the *encrypted* bit
|
234
|
+
def encrypted?
|
225
235
|
|
226
|
-
|
227
|
-
def compressed?
|
236
|
+
return false if @file_stat.nil?
|
228
237
|
|
229
|
-
|
238
|
+
@file_stat.encrypted?
|
239
|
+
end
|
240
|
+
end
|
230
241
|
|
231
|
-
|
232
|
-
|
242
|
+
# indicates whether the given entry represents a directory
|
243
|
+
def directory?
|
233
244
|
|
234
|
-
|
235
|
-
def encrypted?
|
245
|
+
return false if @file_stat.nil?
|
236
246
|
|
237
|
-
|
247
|
+
@file_stat.directory?
|
248
|
+
end
|
238
249
|
|
239
|
-
|
240
|
-
end
|
241
|
-
end
|
250
|
+
alias_method :dir?, :directory?
|
242
251
|
|
243
|
-
|
244
|
-
|
252
|
+
# indicates whether the given entry represents a file
|
253
|
+
def file?
|
245
254
|
|
246
|
-
|
255
|
+
return false if @file_stat.nil?
|
247
256
|
|
248
|
-
|
249
|
-
|
257
|
+
@file_stat.file?
|
258
|
+
end
|
250
259
|
|
251
|
-
|
260
|
+
# indicates whether the given entry represents a link
|
261
|
+
def link?
|
252
262
|
|
253
|
-
|
254
|
-
def file?
|
263
|
+
return false if @file_stat.nil?
|
255
264
|
|
256
|
-
|
265
|
+
@file_stat.link?
|
266
|
+
end
|
257
267
|
|
258
|
-
|
259
|
-
|
268
|
+
# indicates whether the given entry represents a socket
|
269
|
+
def socket?
|
260
270
|
|
261
|
-
|
262
|
-
def link?
|
271
|
+
return false if @file_stat.nil?
|
263
272
|
|
264
|
-
|
273
|
+
@file_stat.socket?
|
274
|
+
end
|
265
275
|
|
266
|
-
|
267
|
-
|
276
|
+
# ##########################
|
277
|
+
# Size attributes
|
268
278
|
|
269
|
-
|
270
|
-
|
279
|
+
# indicates the size of the given entry
|
280
|
+
def size
|
271
281
|
|
272
|
-
|
282
|
+
return 0 if @file_stat.nil?
|
273
283
|
|
274
|
-
|
275
|
-
|
284
|
+
@file_stat.size
|
285
|
+
end
|
276
286
|
|
277
|
-
|
278
|
-
|
287
|
+
# ##########################
|
288
|
+
# File-system entry attributes
|
279
289
|
|
280
|
-
|
281
|
-
|
290
|
+
# indicates the device of the given entry
|
291
|
+
#
|
292
|
+
# On Windows, this will be 0 if the entry cannot be
|
293
|
+
# opened
|
294
|
+
def dev
|
282
295
|
|
283
|
-
|
296
|
+
@dev
|
297
|
+
end
|
284
298
|
|
285
|
-
|
286
|
-
|
299
|
+
# indicates the ino of the given entry
|
300
|
+
#
|
301
|
+
# On Windows, this will be 0 if the entry cannot be
|
302
|
+
# opened
|
303
|
+
def ino
|
287
304
|
|
288
|
-
|
289
|
-
|
305
|
+
@ino
|
306
|
+
end
|
290
307
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
308
|
+
# number of links to the given entry
|
309
|
+
#
|
310
|
+
# On Windows, this will be 0 if the entry cannot be
|
311
|
+
# opened
|
312
|
+
def nlink
|
296
313
|
|
297
|
-
|
298
|
-
|
314
|
+
@nlink
|
315
|
+
end
|
299
316
|
|
300
|
-
|
301
|
-
|
302
|
-
# On Windows, this will be 0 if the entry cannot be
|
303
|
-
# opened
|
304
|
-
def ino
|
317
|
+
# ##########################
|
318
|
+
# Time attributes
|
305
319
|
|
306
|
-
|
307
|
-
|
320
|
+
# indicates the last access time of the entry
|
321
|
+
def last_access_time
|
308
322
|
|
309
|
-
|
310
|
-
#
|
311
|
-
# On Windows, this will be 0 if the entry cannot be
|
312
|
-
# opened
|
313
|
-
def nlink
|
323
|
+
return nil if @file_stat.nil?
|
314
324
|
|
315
|
-
|
316
|
-
|
325
|
+
@file_stat.atime
|
326
|
+
end
|
317
327
|
|
318
|
-
|
319
|
-
|
328
|
+
# indicates the modification time of the entry
|
329
|
+
def modification_time
|
320
330
|
|
321
|
-
|
322
|
-
def last_access_time
|
331
|
+
return nil if @file_stat.nil?
|
323
332
|
|
324
|
-
|
333
|
+
@file_stat.mtime
|
334
|
+
end
|
325
335
|
|
326
|
-
|
327
|
-
|
336
|
+
# ##########################
|
337
|
+
# Comparison
|
328
338
|
|
329
|
-
|
330
|
-
|
339
|
+
# determines whether rhs is an instance of Entry and
|
340
|
+
# refers to the same path
|
341
|
+
def eql?(rhs)
|
331
342
|
|
332
|
-
|
343
|
+
case rhs
|
344
|
+
when self.class
|
333
345
|
|
334
|
-
|
335
|
-
|
346
|
+
return compare_path == rhs.compare_path
|
347
|
+
else
|
336
348
|
|
337
|
-
|
338
|
-
|
349
|
+
return false
|
350
|
+
end
|
351
|
+
end
|
339
352
|
|
340
|
-
|
341
|
-
|
342
|
-
def eql?(rhs)
|
353
|
+
# determines whether rhs refers to the same path
|
354
|
+
def ==(rhs)
|
343
355
|
|
344
|
-
|
345
|
-
|
346
|
-
return compare_path == rhs.compare_path
|
347
|
-
else
|
348
|
-
return false
|
349
|
-
end
|
350
|
-
end
|
356
|
+
case rhs
|
357
|
+
when String
|
351
358
|
|
352
|
-
|
353
|
-
|
359
|
+
return compare_path == Entry.get_compare_path_(rhs)
|
360
|
+
when self.class
|
354
361
|
|
355
|
-
|
356
|
-
|
357
|
-
return compare_path == Entry.get_compare_path_(rhs)
|
358
|
-
when self.class
|
359
|
-
return compare_path == rhs.compare_path
|
360
|
-
else
|
361
|
-
return false
|
362
|
-
end
|
363
|
-
end
|
362
|
+
return compare_path == rhs.compare_path
|
363
|
+
else
|
364
364
|
|
365
|
-
|
366
|
-
|
365
|
+
return false
|
366
|
+
end
|
367
|
+
end
|
367
368
|
|
368
|
-
|
369
|
-
|
369
|
+
# compares this instance with rhs
|
370
|
+
def <=>(rhs)
|
370
371
|
|
371
|
-
|
372
|
-
|
372
|
+
compare_path <=> rhs.compare_path
|
373
|
+
end
|
373
374
|
|
374
|
-
|
375
|
-
|
375
|
+
# the hash
|
376
|
+
def hash
|
376
377
|
|
377
|
-
|
378
|
-
|
378
|
+
@hash
|
379
|
+
end
|
379
380
|
|
380
|
-
|
381
|
-
|
382
|
-
def to_s
|
381
|
+
# ##########################
|
382
|
+
# Conversion
|
383
383
|
|
384
|
-
|
385
|
-
|
384
|
+
# represents the entry as a string (in the form of
|
385
|
+
# the full path)
|
386
|
+
def to_s
|
386
387
|
|
387
|
-
|
388
|
-
|
389
|
-
def to_str
|
388
|
+
path
|
389
|
+
end
|
390
390
|
|
391
|
-
|
392
|
-
|
393
|
-
|
391
|
+
# represents the entry as a string (in the form of
|
392
|
+
# the full path)
|
393
|
+
def to_str
|
394
|
+
|
395
|
+
path
|
396
|
+
end
|
397
|
+
end # class Entry
|
394
398
|
end # module Recls
|
395
399
|
|
396
|
-
# ############################## end of file ############################# #
|
397
400
|
|
401
|
+
# ############################## end of file ############################# #
|
398
402
|
|