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