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