recls-ruby 2.11.0 → 2.11.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 +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