recls-ruby 2.12.0 → 2.12.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  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 +76 -73
  11. data/lib/recls/combine_paths_1.rb +26 -23
  12. data/lib/recls/combine_paths_2plus.rb +32 -29
  13. data/lib/recls/entry.rb +277 -273
  14. data/lib/recls/file_search.rb +194 -193
  15. data/lib/recls/flags.rb +48 -45
  16. data/lib/recls/foreach.rb +105 -98
  17. data/lib/recls/obsolete.rb +85 -79
  18. data/lib/recls/recls.rb +19 -24
  19. data/lib/recls/stat.rb +137 -134
  20. data/lib/recls/util.rb +95 -92
  21. data/lib/recls/version.rb +22 -17
  22. data/lib/recls/ximpl/os.rb +49 -48
  23. data/lib/recls/ximpl/unix.rb +41 -38
  24. data/lib/recls/ximpl/util.rb +600 -599
  25. data/lib/recls/ximpl/windows.rb +142 -139
  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 +7 -7
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,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
- # 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
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
- # Nature attributes
164
+ not @file_stat.nil?
165
+ end
155
166
 
156
- # indicates whether the given entry existed at the time the entry
157
- # instance was created
158
- def exist?
167
+ # indicates whether the given entry is hidden
168
+ def hidden?
159
169
 
160
- return false if @file_stat.nil?
170
+ return false if @file_stat.nil?
161
171
 
162
- not @file_stat.nil?
163
- end
172
+ @file_stat.hidden?
173
+ end
164
174
 
165
- # indicates whether the given entry is hidden
166
- def hidden?
175
+ # indicates whether the given entry is readonly
176
+ def readonly?
167
177
 
168
- return false if @file_stat.nil?
178
+ return false if @file_stat.nil?
169
179
 
170
- @file_stat.hidden?
171
- end
180
+ not @file_stat.writable?
181
+ end
172
182
 
173
- # indicates whether the given entry is readonly
174
- def readonly?
183
+ if Recls::Ximpl::OS::OS_IS_WINDOWS
175
184
 
176
- return false if @file_stat.nil?
185
+ # [WINDOWS-ONLY] Indicates whether the entry has the *system* bit
186
+ def system?
177
187
 
178
- not @file_stat.writable?
179
- end
188
+ return false if @file_stat.nil?
180
189
 
181
- # ##########################
182
- # Comparison
190
+ @file_stat.system?
191
+ end
183
192
 
184
- if Recls::Ximpl::OS::OS_IS_WINDOWS
193
+ # [WINDOWS-ONLY] Indicates whether the entry has the *archive* bit
194
+ def archive?
185
195
 
186
- # [WINDOWS-ONLY] Indicates whether the entry has the *system* bit
187
- def system?
196
+ return false if @file_stat.nil?
188
197
 
189
- return false if @file_stat.nil?
198
+ @file_stat.archive?
199
+ end
190
200
 
191
- @file_stat.system?
192
- end
201
+ # [WINDOWS-ONLY] Indicates whether the entry is a device
202
+ def device?
193
203
 
194
- # [WINDOWS-ONLY] Indicates whether the entry has the *archive* bit
195
- def archive?
204
+ return false if @file_stat.nil?
196
205
 
197
- return false if @file_stat.nil?
206
+ @file_stat.device?
207
+ end
198
208
 
199
- @file_stat.archive?
200
- end
209
+ # [WINDOWS-ONLY] Indicates whether the entry is *normal*
210
+ def normal?
201
211
 
202
- # [WINDOWS-ONLY] Indicates whether the entry is a device
203
- def device?
212
+ return false if @file_stat.nil?
204
213
 
205
- return false if @file_stat.nil?
214
+ @file_stat.normal?
215
+ end
206
216
 
207
- @file_stat.device?
208
- end
217
+ # [WINDOWS-ONLY] Indicates whether the entry has the *temporary* bit
218
+ def temporary?
209
219
 
210
- # [WINDOWS-ONLY] Indicates whether the entry is *normal*
211
- def normal?
220
+ return false if @file_stat.nil?
212
221
 
213
- return false if @file_stat.nil?
222
+ @file_stat.temporary?
223
+ end
214
224
 
215
- @file_stat.normal?
216
- end
225
+ # [WINDOWS-ONLY] Indicates whether the entry has the *compressed* bit
226
+ def compressed?
217
227
 
218
- # [WINDOWS-ONLY] Indicates whether the entry has the *temporary* bit
219
- def temporary?
228
+ return false if @file_stat.nil?
220
229
 
221
- return false if @file_stat.nil?
230
+ @file_stat.compressed?
231
+ end
222
232
 
223
- @file_stat.temporary?
224
- end
233
+ # [WINDOWS-ONLY] Indicates whether the entry has the *encrypted* bit
234
+ def encrypted?
225
235
 
226
- # [WINDOWS-ONLY] Indicates whether the entry has the *compressed* bit
227
- def compressed?
236
+ return false if @file_stat.nil?
228
237
 
229
- return false if @file_stat.nil?
238
+ @file_stat.encrypted?
239
+ end
240
+ end
230
241
 
231
- @file_stat.compressed?
232
- end
242
+ # indicates whether the given entry represents a directory
243
+ def directory?
233
244
 
234
- # [WINDOWS-ONLY] Indicates whether the entry has the *encrypted* bit
235
- def encrypted?
245
+ return false if @file_stat.nil?
236
246
 
237
- return false if @file_stat.nil?
247
+ @file_stat.directory?
248
+ end
238
249
 
239
- @file_stat.encrypted?
240
- end
241
- end
250
+ alias_method :dir?, :directory?
242
251
 
243
- # indicates whether the given entry represents a directory
244
- def directory?
252
+ # indicates whether the given entry represents a file
253
+ def file?
245
254
 
246
- return false if @file_stat.nil?
255
+ return false if @file_stat.nil?
247
256
 
248
- @file_stat.directory?
249
- end
257
+ @file_stat.file?
258
+ end
250
259
 
251
- alias_method :dir?, :directory?
260
+ # indicates whether the given entry represents a link
261
+ def link?
252
262
 
253
- # indicates whether the given entry represents a file
254
- def file?
263
+ return false if @file_stat.nil?
255
264
 
256
- return false if @file_stat.nil?
265
+ @file_stat.link?
266
+ end
257
267
 
258
- @file_stat.file?
259
- end
268
+ # indicates whether the given entry represents a socket
269
+ def socket?
260
270
 
261
- # indicates whether the given entry represents a link
262
- def link?
271
+ return false if @file_stat.nil?
263
272
 
264
- return false if @file_stat.nil?
273
+ @file_stat.socket?
274
+ end
265
275
 
266
- @file_stat.link?
267
- end
276
+ # ##########################
277
+ # Size attributes
268
278
 
269
- # indicates whether the given entry represents a socket
270
- def socket?
279
+ # indicates the size of the given entry
280
+ def size
271
281
 
272
- return false if @file_stat.nil?
282
+ return 0 if @file_stat.nil?
273
283
 
274
- @file_stat.socket?
275
- end
284
+ @file_stat.size
285
+ end
276
286
 
277
- # ##########################
278
- # Size attributes
287
+ # ##########################
288
+ # File-system entry attributes
279
289
 
280
- # indicates the size of the given entry
281
- def size
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
- return 0 if @file_stat.nil?
296
+ @dev
297
+ end
284
298
 
285
- @file_stat.size
286
- end
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
- # File-system entry attributes
305
+ @ino
306
+ end
290
307
 
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
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
- @dev
298
- end
314
+ @nlink
315
+ end
299
316
 
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
317
+ # ##########################
318
+ # Time attributes
305
319
 
306
- @ino
307
- end
320
+ # indicates the last access time of the entry
321
+ def last_access_time
308
322
 
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
323
+ return nil if @file_stat.nil?
314
324
 
315
- @nlink
316
- end
325
+ @file_stat.atime
326
+ end
317
327
 
318
- # ##########################
319
- # Time attributes
328
+ # indicates the modification time of the entry
329
+ def modification_time
320
330
 
321
- # indicates the last access time of the entry
322
- def last_access_time
331
+ return nil if @file_stat.nil?
323
332
 
324
- return nil if @file_stat.nil?
333
+ @file_stat.mtime
334
+ end
325
335
 
326
- @file_stat.atime
327
- end
336
+ # ##########################
337
+ # Comparison
328
338
 
329
- # indicates the modification time of the entry
330
- def modification_time
339
+ # determines whether rhs is an instance of Entry and
340
+ # refers to the same path
341
+ def eql?(rhs)
331
342
 
332
- return nil if @file_stat.nil?
343
+ case rhs
344
+ when self.class
333
345
 
334
- @file_stat.mtime
335
- end
346
+ return compare_path == rhs.compare_path
347
+ else
336
348
 
337
- # ##########################
338
- # Comparison
349
+ return false
350
+ end
351
+ end
339
352
 
340
- # determines whether rhs is an instance of Entry and
341
- # refers to the same path
342
- def eql?(rhs)
353
+ # determines whether rhs refers to the same path
354
+ def ==(rhs)
343
355
 
344
- case rhs
345
- when self.class
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
- # determines whether rhs refers to the same path
353
- def ==(rhs)
359
+ return compare_path == Entry.get_compare_path_(rhs)
360
+ when self.class
354
361
 
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
362
+ return compare_path == rhs.compare_path
363
+ else
364
364
 
365
- # compares this instance with rhs
366
- def <=>(rhs)
365
+ return false
366
+ end
367
+ end
367
368
 
368
- compare_path <=> rhs.compare_path
369
- end
369
+ # compares this instance with rhs
370
+ def <=>(rhs)
370
371
 
371
- # the hash
372
- def hash
372
+ compare_path <=> rhs.compare_path
373
+ end
373
374
 
374
- @hash
375
- end
375
+ # the hash
376
+ def hash
376
377
 
377
- # ##########################
378
- # Conversion
378
+ @hash
379
+ end
379
380
 
380
- # represents the entry as a string (in the form of
381
- # the full path)
382
- def to_s
381
+ # ##########################
382
+ # Conversion
383
383
 
384
- path
385
- end
384
+ # represents the entry as a string (in the form of
385
+ # the full path)
386
+ def to_s
386
387
 
387
- # represents the entry as a string (in the form of
388
- # the full path)
389
- def to_str
388
+ path
389
+ end
390
390
 
391
- path
392
- end
393
- end # class Entry
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