rbfind 1.13 → 2.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/bin/rbfind +413 -416
- data/lib/rbfind.rb +568 -731
- data/lib/rbfind/core.rb +82 -0
- data/lib/rbfind/csv.rb +54 -0
- data/lib/{humansiz.rb → rbfind/humansiz.rb} +30 -9
- data/lib/rbfind/table.rb +114 -0
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a6e7b3de72cc2efdb3033593f8ffac176da6dab3395d68594570d08c3992249
|
4
|
+
data.tar.gz: 36f03f0b41bd1180429bd527f0fa7f6a8f8e2897c3f99569fbc6250f3e358baf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b30427e248f24b028eb554b5c5672d96695f7fdec4c87e3ae39343671702c89e02664a78ac6bbc40f101baa348fbebc67c9a5e564f8694d27e9d53b1bc7cd103
|
7
|
+
data.tar.gz: 847dbf390ec156f619b06c1820e5df1ca4d51f89b8ebc7ae06f7a055d98bd734d74a7ae6d122e5c58d5eaa0ce183afba0a70db1856801d62bd413c49988ad6b4
|
data/bin/rbfind
CHANGED
@@ -5,137 +5,423 @@
|
|
5
5
|
#
|
6
6
|
|
7
7
|
require "rbfind"
|
8
|
+
require "rbfind/humansiz"
|
9
|
+
require "English"
|
10
|
+
require 'getoptlong'
|
8
11
|
|
9
|
-
PROGRAM = <<EOT
|
10
|
-
rbfind #{RbFind::VERSION} -- A find tool using Ruby
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
module RbFind
|
14
|
+
|
15
|
+
class Application
|
16
|
+
|
17
|
+
PROGRAM = <<~EOT
|
18
|
+
rbfind #{RbFind::VERSION} -- A find tool using Ruby
|
19
|
+
|
20
|
+
Author: Bertram Scharpf <software@bertram-scharpf.de>
|
21
|
+
License: BSD
|
22
|
+
EOT
|
23
|
+
|
24
|
+
OPTIONS = [
|
25
|
+
# options arg description
|
26
|
+
[ %w(--help -h), nil, "print this help"],
|
27
|
+
[ %w(--examples -X), nil, "print this help and examples"],
|
28
|
+
[ %w(--version -V), nil, "print version information"],
|
29
|
+
[ %w(--verbose -v), nil, "standard Ruby error reports"],
|
30
|
+
[ %w(--show -o), nil, "just show Ruby block built from options"],
|
31
|
+
[ %w(--bw -w), nil, "black and white on -p or default output"],
|
32
|
+
[ %w(--colored -c), nil, "force color on -p or default output"],
|
33
|
+
[ %w(--depth -d), nil, "yield directory after its contents"],
|
34
|
+
[ %w(--maxdepth -m), :num, "maxium step depth"],
|
35
|
+
[ %w(--follow -y), nil, "follow symbolic links"],
|
36
|
+
[ %w(--nosort -S), nil, "unsorted"],
|
37
|
+
[ %w(--sort-by -s), :str, "sort expression ('n' is name)"],
|
38
|
+
[ %w(--reverse -R), :str, "reverse sort"],
|
39
|
+
[ %w(--require -r), :rb, "require library"],
|
40
|
+
[ %w(--fileutils -U), nil, "include FileUtils module"],
|
41
|
+
[ %w(--puts-path -p), nil, "do 'puts path/cpath' on true block"],
|
42
|
+
[ %w(--ls-l -P), nil, "do 'ls -l' style output on true block"],
|
43
|
+
[ %w(--wider -+), nil, "widen fields in long output format (--ls-l)"],
|
44
|
+
[ %w(--slash -/), nil, "append a slash to directory names"],
|
45
|
+
[ %w(--lines -l), :blk, "surround block by 'lines { |$_,$.| ... }'"],
|
46
|
+
[ %w(--reallines -L), :blk, "same as -l but stop at any null character"],
|
47
|
+
[ %w(--grep -g), :blk, "grep files (implies -pL)"],
|
48
|
+
[ %w(--igrep -G), :blk, "case insensitive grep"],
|
49
|
+
[ %w(--binary -b), nil, "grep even binary files"],
|
50
|
+
[ %w(--no-vcs -C), nil, "prune version control dirs (CVS/.svn/.git)"],
|
51
|
+
[ %w(--no-swap -W), nil, "ignore Vim swapfiles"],
|
52
|
+
[ %w(--skip -k), :lst, "filenames to skip"],
|
53
|
+
[ %w(--demand -D), :lst, "skip all filenames but these"],
|
54
|
+
[ %w(--ext -e), :lst, "skip all filename extensions but these"],
|
55
|
+
[ %w(--visible -I), nil, "skip all hidden (starting with .dot)"],
|
56
|
+
[ %w(--nodirs -N), nil, "skip directories"],
|
57
|
+
[ %w(--begin -B), :blk, "eval block before begin"],
|
58
|
+
[ %w(--end -E), :blk, "eval block after end"],
|
59
|
+
[ %w(--file -f), :blk, "read block expression from file"],
|
60
|
+
[ %w(--encoding -K), :str, "encoding extern[:intern] (same as ruby -E)"],
|
61
|
+
]
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
@params = {}
|
65
|
+
envopts = ENV[ "RBFIND_OPTIONS"]
|
66
|
+
$*.unshift *envopts.split if envopts
|
67
|
+
opts = GetoptLong.new *OPTIONS.map { |(long,short),arg,|
|
68
|
+
[long,short,(arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT)]
|
69
|
+
}
|
70
|
+
opts.ordering = GetoptLong::PERMUTE
|
71
|
+
opts.quiet = true
|
72
|
+
opts.each do |opt,arg|
|
73
|
+
case opt
|
74
|
+
when '--help' then usage ; exit
|
75
|
+
when '--version' then puts PROGRAM ; exit
|
76
|
+
when '--examples' then usage_examples ; exit
|
77
|
+
when '--verbose' then @verbose = true
|
78
|
+
when '--show' then @show = true
|
79
|
+
when '--bw' then @color = false
|
80
|
+
when '--colored' then @color = true
|
81
|
+
when '--depth' then @params[ :depth_first] = true
|
82
|
+
when '--maxdepth' then @params[ :max_depth] = arg.to_i
|
83
|
+
when '--follow' then @params[ :follow] = true
|
84
|
+
when '--nosort' then @params[ :sort] = false
|
85
|
+
when '--sort-by' then @params[ :sort] = instance_eval "proc { |n| #{arg} }"
|
86
|
+
when '--reverse' then @params[ :reverse] = true
|
87
|
+
when '--require' then require arg
|
88
|
+
when '--fileutils' then require "fileutils" ; include FileUtils
|
89
|
+
when '--puts-path' then @puts = true
|
90
|
+
when '--ls-l' then @puts = true ; @wd = 6
|
91
|
+
when '--wider' then @wd = @wd ? @wd.succ : 4
|
92
|
+
when '--slash' then @slash = true
|
93
|
+
when '--lines' then @lines = :plain ; @block = arg
|
94
|
+
when '--reallines' then @lines = :plain ; @real = true ; @block = arg
|
95
|
+
when '--grep' then @lines = :grep ; @block = arg
|
96
|
+
when '--igrep' then @lines = :grep ; @icase = true ; @block = arg
|
97
|
+
when '--binary' then @binary = true
|
98
|
+
when '--no-vcs' then @vcs = true
|
99
|
+
when '--no-swap' then @vim = true
|
100
|
+
when '--skip' then @skip = arg
|
101
|
+
when '--demand' then @demand = arg
|
102
|
+
when '--ext' then @ext = arg
|
103
|
+
when '--visible' then @visible = true
|
104
|
+
when '--nodirs' then @nodirs = true
|
105
|
+
when '--begin' then @blkbegin = arg
|
106
|
+
when '--end' then @blkend = arg
|
107
|
+
when '--file' then @block = File.read arg
|
108
|
+
when '--encoding' then e, i = arg.split ":" ; set_encoding e, i
|
109
|
+
end
|
110
|
+
end
|
111
|
+
@args = $*.dup
|
112
|
+
if @args.empty? and not $stdin.tty? then
|
113
|
+
$stdin.each_line { |l|
|
114
|
+
l.chomp!
|
115
|
+
@args.push l
|
116
|
+
}
|
117
|
+
end
|
118
|
+
build_block
|
119
|
+
rescue GetoptLong::InvalidOption
|
120
|
+
$stderr.puts $!
|
121
|
+
$stderr.puts
|
122
|
+
usage
|
123
|
+
exit 9
|
124
|
+
rescue
|
125
|
+
$stderr.puts $!
|
126
|
+
exit 8
|
127
|
+
end
|
15
128
|
|
129
|
+
def build_block
|
130
|
+
co = color_on $stdout
|
131
|
+
opath = co ? "cpath" : "path"
|
132
|
+
@slash and opath << "!"
|
133
|
+
case @lines
|
134
|
+
when :plain then
|
135
|
+
@puts and @block = "( #@block ) and colsep #{opath}, num, line"
|
136
|
+
@real and @block = "break if ~/\0/o ; #@block"
|
137
|
+
@block = "lines { |line,num| #@block }"
|
138
|
+
|
139
|
+
when :grep then
|
140
|
+
re = Regexp.new @block, @icase && Regexp::IGNORECASE
|
141
|
+
@block = "grep #{re.inspect}"
|
142
|
+
@block << ", true" if co
|
143
|
+
@block << " ; $stdout.flush" unless $stdout.tty?
|
144
|
+
@binary or @block = "not binary? and (#@block)"
|
16
145
|
|
17
|
-
|
146
|
+
else
|
147
|
+
@block ||= if @args.last and not (File.exists? @args.last) then
|
148
|
+
@args.pop.dup
|
149
|
+
else
|
150
|
+
@puts ||= true
|
151
|
+
"true"
|
152
|
+
end
|
153
|
+
if @puts then
|
154
|
+
@block = "( #@block ) and "
|
155
|
+
@block << if @wd then
|
156
|
+
"spcsep stype+modes, user.w#@wd, group.w#@wd, size.w#@wd, " +
|
157
|
+
"mtime.lsish, #{opath} + #{co ? 'carrow' : 'arrow'}.to_s"
|
158
|
+
else
|
159
|
+
"puts #{opath}"
|
160
|
+
end
|
161
|
+
end
|
18
162
|
|
19
|
-
|
20
|
-
# options arg description
|
21
|
-
[ %w(--help -h), nil, "print this help"],
|
22
|
-
[ %w(--examples -X), nil, "print this help and examples"],
|
23
|
-
[ %w(--version -V), nil, "print version information"],
|
24
|
-
[ %w(--verbose -v), nil, "standard Ruby error reports"],
|
25
|
-
[ %w(--show -o), nil, "just show Ruby block built from options"],
|
26
|
-
[ %w(--bw -w), nil, "black and white on -p or default output"],
|
27
|
-
[ %w(--colored -c), nil, "force color on -p or default output"],
|
28
|
-
[ %w(--depth -d), nil, "yield directory after its contents"],
|
29
|
-
[ %w(--maxdepth -m), :num, "maxium step depth"],
|
30
|
-
[ %w(--follow -y), nil, "follow symbolic links"],
|
31
|
-
[ %w(--sort -s), :str, "=reverse/desc/-1,unsorted; default is sorted"],
|
32
|
-
[ %w(--sort-by -S), :str, "sort expression ('name' is name)"],
|
33
|
-
[ %w(--require -r), :rb, "require library"],
|
34
|
-
[ %w(--fileutils -U), nil, "include FileUtils module"],
|
35
|
-
[ %w(--puts-path -p), nil, "do 'puts path/cpath' on true block"],
|
36
|
-
[ %w(--ls-l -P), nil, "do 'ls -l' style output on true block"],
|
37
|
-
[ %w(--wider -+), nil, "widen fields in long output format (--ls-l)"],
|
38
|
-
[ %w(--slash -/), nil, "append a slash to directory names"],
|
39
|
-
[ %w(--lines -l), :blk, "surround block by 'lines { |$_,$.| ... }'"],
|
40
|
-
[ %w(--reallines -L), :blk, "same as -l but stop at any null character"],
|
41
|
-
[ %w(--grep -g), :blk, "grep files (implies -pL)"],
|
42
|
-
[ %w(--igrep -G), :blk, "case insensitive grep"],
|
43
|
-
[ %w(--binary -b), nil, "grep even binary files"],
|
44
|
-
[ %w(--no-vcs -C), nil, "prune version control dirs (CVS/.svn/.git)"],
|
45
|
-
[ %w(--no-swap -W), nil, "ignore Vim swapfiles"],
|
46
|
-
[ %w(--skip -k), :lst, "filenames to skip"],
|
47
|
-
[ %w(--demand -D), :lst, "skip all filenames but these"],
|
48
|
-
[ %w(--ext -e), :lst, "skip all filename extensions but these"],
|
49
|
-
[ %w(--visible -I), nil, "skip all hidden (starting with .dot)"],
|
50
|
-
[ %w(--nodirs -N), nil, "skip directories"],
|
51
|
-
[ %w(--begin -B), :blk, "eval block before begin"],
|
52
|
-
[ %w(--end -E), :blk, "eval block after end"],
|
53
|
-
[ %w(--file -f), :blk, "read block expression from file"],
|
54
|
-
[ %w(--encoding -K), :str, "encoding extern[:intern] (same as ruby -E)"],
|
55
|
-
]
|
56
|
-
|
57
|
-
def usage
|
58
|
-
puts <<EOT
|
59
|
-
Usage:
|
60
|
-
|
61
|
-
rbfind [options] path... 'block'
|
62
|
-
|
63
|
-
EOT
|
64
|
-
OPTIONS.each { |(long,short),arg,desc|
|
65
|
-
puts " %-12s %2s %-5s %s" % [long,short,arg.to_s.upcase,desc]
|
66
|
-
}
|
67
|
-
puts <<'EOT'
|
68
|
-
|
69
|
-
"--" stops option processing.
|
70
|
-
|
71
|
-
The last argument is a block that will be executed on every found
|
72
|
-
file object. It may be omitted; then "puts path" is assumed or "cpath"
|
73
|
-
in case the output is a terminal.
|
74
|
-
|
75
|
-
Default sort order is alphabetical.
|
76
|
-
|
77
|
-
EOT
|
78
|
-
end
|
163
|
+
end
|
79
164
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
$ rbfind -p 'file and age > 1.d'
|
86
|
-
$ rbfind -p '(90.d .. 183.d) === age'
|
87
|
-
|
88
|
-
$ rbfind -Cg require
|
89
|
-
$ rbfind -Cp
|
90
|
-
$ rbfind 'filesize < 100.kB and grep /require/'
|
91
|
-
$ rbfind -g 'define\s*ALLOC_N'
|
92
|
-
$ rbfind myproject -e rb -l '~/require/ and puts $_'
|
93
|
-
|
94
|
-
$ rbfind -pe '.rb c h'
|
95
|
-
$ rbfind /usr/include -e .h -g EACCES
|
96
|
-
$ rbfind -d -m3 -- /mnt/data
|
97
|
-
$ rbfind 'filesize > 10.MiB and colsep size.to_hib, path'
|
98
|
-
|
99
|
-
$ rbfind -S "name =~ /^\.*/ ; $'.downcase"
|
100
|
-
$ rbfind -B '$s=0' -E 'puts $s.to_h' 'filesize {|s|$s+=s}'
|
101
|
-
$ rbfind 'puts path if ext == ".rb"'
|
102
|
-
$ rbfind -p 'ext == ".rb"'
|
103
|
-
$ rbfind /usr/include -p -D '\.h$' -l '~/EACCES/'
|
104
|
-
$ rbfind /usr/include -pD 'pg|pq|postgres' dir
|
105
|
-
$ rbfind 'no_svn ; puts path'
|
106
|
-
$ rbfind 'prune if name == ".svn" ; puts path'
|
107
|
-
$ rbfind -p 'prune if name == ".svn"'
|
108
|
-
$ rbfind myproject 'name[/\.rb$/] and lines { |l,i| l=~/require/ and puts l }'
|
109
|
-
# rbfind /etc 'lines { |l,| l["192.168."] and (puts path ; break) }'
|
110
|
-
$ rbfind /etc 'readable? or raise "Access denied: #{path}" ;
|
111
|
-
> lines { |l,| l["192.168."] and (puts path ; break) }'
|
112
|
-
|
113
|
-
$ rbfind 'col_sep stype+modes, size.w10, path'
|
114
|
-
$ rbfind 'tab_sep stype+modes, size.w10, path'
|
115
|
-
$ rbfind 'spc_sep stype+modes, size.to_h, user, group, mtime.lsish, path'
|
116
|
-
$ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime.lsish, path'
|
117
|
-
$ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime!, path'
|
118
|
-
$ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime.i, path'
|
119
|
-
$ rbfind 'spacesep mtime.u, path'
|
120
|
-
$ rbfind 'spacesep modes, user.w8, group.w8, size.w8, cpath + carrow.to_s'
|
121
|
-
|
122
|
-
$ rbfind 'spacesep digest_md5, size.w8, path'
|
123
|
-
$ rbfind 'spacesep digest_sha256, size.w8, path'
|
124
|
-
|
125
|
-
$ rbfind 'rename name.downcase'
|
126
|
-
$ rbfind 'ext == ".tgz" and rename without_ext+".tar.gz"'
|
127
|
-
|
128
|
-
See the RbFind class documentation or the "rbfind.rb" source file for more
|
129
|
-
sophisticated examples and for a full list of file examination methods.
|
130
|
-
|
131
|
-
Valid units are 1.s, 1.m, 1.h, 1.d, 1.w for time values and
|
132
|
-
1.kB == 1000, 1.kiB == 1024, 1.MB, 1.MiB for file sizes.
|
133
|
-
EOT
|
134
|
-
end
|
165
|
+
osic = File::ALT_SEPARATOR&&Regexp::IGNORECASE
|
166
|
+
if @skip then
|
167
|
+
re = Regexp.new @skip, osic
|
168
|
+
@block.insert 0, "done if name =~ #{re.inspect} ; "
|
169
|
+
end
|
135
170
|
|
171
|
+
if @demand then
|
172
|
+
re = Regexp.new @demand, osic
|
173
|
+
@block.insert 0, "done unless name =~ #{re.inspect} ; "
|
174
|
+
end
|
136
175
|
|
137
|
-
|
138
|
-
|
176
|
+
if @ext then
|
177
|
+
re = Regexp.new '\A\.(' +
|
178
|
+
@ext.split(/ +|,/).map { |e| e[ /\A\.?(.*)\z/, 1] }.join('|') +
|
179
|
+
')\z', osic
|
180
|
+
@block.insert 0, "ext =~ #{re.inspect} or done ; "
|
181
|
+
end
|
182
|
+
|
183
|
+
@visible and @block.insert 0, "visible? or done ; "
|
184
|
+
|
185
|
+
@nodirs and @block.insert 0, "done if dir? ; "
|
186
|
+
|
187
|
+
@vcs and @block.insert 0, "no_vcs ; "
|
188
|
+
@vim and @block.insert 0, "vimswap? and done ; "
|
189
|
+
|
190
|
+
@params[ :error] = proc do
|
191
|
+
case $!
|
192
|
+
when Errno::EPIPE then raise
|
193
|
+
when NameError, TypeError then raise
|
194
|
+
when ArgumentError then raise
|
195
|
+
else show_error $!
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def run
|
201
|
+
if @show then
|
202
|
+
show
|
203
|
+
else
|
204
|
+
execute
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def usage
|
211
|
+
puts <<~EOT
|
212
|
+
Usage:
|
213
|
+
|
214
|
+
rbfind [options] path... 'block'
|
215
|
+
|
216
|
+
EOT
|
217
|
+
OPTIONS.each { |(long,short),arg,desc|
|
218
|
+
puts " %-12s %2s %-5s %s" % [long,short,arg.to_s.upcase,desc]
|
219
|
+
}
|
220
|
+
puts <<~'EOT'
|
221
|
+
|
222
|
+
"--" stops option processing.
|
223
|
+
|
224
|
+
The last argument is a block that will be executed on every found
|
225
|
+
file object. It may be omitted; then "puts path" is assumed or "cpath"
|
226
|
+
in case the output is a terminal.
|
227
|
+
|
228
|
+
Default sort order is alphabetical.
|
229
|
+
EOT
|
230
|
+
end
|
231
|
+
|
232
|
+
def usage_examples
|
233
|
+
usage
|
234
|
+
puts <<~'EOT'
|
235
|
+
Examples:
|
236
|
+
$ rbfind -p 'file and age < 5.m'
|
237
|
+
$ rbfind -p 'file and age > 1.d'
|
238
|
+
$ rbfind -p '(90.d .. 183.d) === age'
|
239
|
+
|
240
|
+
$ rbfind -Cg require
|
241
|
+
$ rbfind -Cp
|
242
|
+
$ rbfind 'filesize < 100.kB and grep /require/'
|
243
|
+
$ rbfind -g 'define\s*ALLOC_N'
|
244
|
+
$ rbfind myproject -e rb -l '~/require/ and puts $_'
|
245
|
+
|
246
|
+
$ rbfind -pe '.rb c h'
|
247
|
+
$ rbfind /usr/include -e .h -g EACCES
|
248
|
+
$ rbfind -d -m3 -- /mnt/data
|
249
|
+
$ rbfind 'filesize > 10.MiB and colsep size.to_hib, path'
|
250
|
+
|
251
|
+
$ rbfind -S "name =~ /^\.*/ ; $'.downcase"
|
252
|
+
$ rbfind -B '$s=0' -E 'puts $s.to_h' 'filesize {|s|$s+=s}'
|
253
|
+
$ rbfind 'puts path if ext == ".rb"'
|
254
|
+
$ rbfind -p 'ext == ".rb"'
|
255
|
+
$ rbfind /usr/include -p -D '\.h$' -l '~/EACCES/'
|
256
|
+
$ rbfind /usr/include -pD 'pg|pq|postgres' dir
|
257
|
+
$ rbfind 'no_svn ; puts path'
|
258
|
+
$ rbfind 'prune if name == ".svn" ; puts path'
|
259
|
+
$ rbfind -p 'prune if name == ".svn"'
|
260
|
+
$ rbfind myproject 'name[/\.rb$/] and lines { |l,i| l=~/require/ and puts l }'
|
261
|
+
# rbfind /etc 'lines { |l,| l["192.168."] and (puts path ; break) }'
|
262
|
+
$ rbfind /etc 'readable? or raise "Access denied: #{path}" ;
|
263
|
+
> lines { |l,| l["192.168."] and (puts path ; break) }'
|
264
|
+
|
265
|
+
$ rbfind 'col_sep stype+modes, size.w10, path'
|
266
|
+
$ rbfind 'tab_sep stype+modes, size.w10, path'
|
267
|
+
$ rbfind 'spc_sep stype+modes, size.to_h, user, group, mtime.lsish, path'
|
268
|
+
$ rbfind 'p stype+modes, size.to_h, user, group, mtime.lsish, path'
|
269
|
+
$ rbfind 'p stype+modes, size.to_h, user, group, mtime!, path'
|
270
|
+
$ rbfind 'p stype+modes, size.to_h, user, group, mtime.i, path'
|
271
|
+
$ rbfind 'p mtime.u, path'
|
272
|
+
$ rbfind 'p modes, user.w8, group.w8, size.w8, cpath + carrow.to_s'
|
273
|
+
|
274
|
+
$ rbfind 'p digest_md5, size.w8, path'
|
275
|
+
$ rbfind 'p digest_sha256, size.w8, path'
|
276
|
+
|
277
|
+
$ rbfind 'rename name.downcase'
|
278
|
+
$ rbfind 'ext == ".tgz" and rename without_ext+".tar.gz"'
|
279
|
+
|
280
|
+
See the RbFind documentation or the "rbfind.rb" source file for more
|
281
|
+
sophisticated examples and for a full list of file examination methods.
|
282
|
+
|
283
|
+
Valid units are 1.s, 1.m, 1.h, 1.d, 1.w for time values and
|
284
|
+
1.kB == 1000, 1.kiB == 1024, 1.MB, 1.MiB for file sizes.
|
285
|
+
EOT
|
286
|
+
end
|
287
|
+
|
288
|
+
def set_encoding extern, intern = nil
|
289
|
+
Encoding.default_external = extern if extern and not extern.empty?
|
290
|
+
Encoding.default_internal = intern if intern and not intern.empty?
|
291
|
+
[ $stdin, $stdout, $stderr].each do |io|
|
292
|
+
io.set_encoding extern, intern
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def color_on stream
|
297
|
+
@color.nil? ? !File::ALT_SEPARATOR && stream.tty? : @color
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
def show_error e
|
302
|
+
co = color_on $stderr
|
303
|
+
$stderr.puts co ? "\e[31m#{e.class}: \e[1m#{e}\e[m" : "#{e.class}: #{e}"
|
304
|
+
end
|
305
|
+
|
306
|
+
def error_handle
|
307
|
+
if @verbose then
|
308
|
+
yield
|
309
|
+
else
|
310
|
+
begin
|
311
|
+
yield
|
312
|
+
rescue ArgumentError
|
313
|
+
show_error $!
|
314
|
+
if $!.message[ "invalid byte sequence"] then
|
315
|
+
$stderr.puts <<~EOT
|
316
|
+
Hint: Try to give a different default encoding by explicitly setting one or
|
317
|
+
by changing the locale.
|
318
|
+
|
319
|
+
$ rbfind -K ascii-8bit ...
|
320
|
+
$ LC_ALL="C" rbfind ...
|
321
|
+
|
322
|
+
Alternatively, you may prefer to scrub the invalid encodings yourself.
|
323
|
+
|
324
|
+
$ rbfind -P 'name.scrub =~ /Fu.ball/'
|
325
|
+
|
326
|
+
EOT
|
327
|
+
end
|
328
|
+
exit 1
|
329
|
+
rescue
|
330
|
+
show_error $!
|
331
|
+
exit 1
|
332
|
+
rescue NoMemoryError, ScriptError, SignalException
|
333
|
+
show_error $!
|
334
|
+
exit 2
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def execute
|
340
|
+
error_handle do
|
341
|
+
eval @blkbegin if @blkbegin
|
342
|
+
b = @block
|
343
|
+
Walk.run *@args, **@params do instance_eval b end
|
344
|
+
eval @blkend if @blkend
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def show
|
349
|
+
puts "arguments:"
|
350
|
+
@args.each { |a| puts_val a }.any? or puts_val "(none)"
|
351
|
+
puts "parameters:"
|
352
|
+
@params.each { |k,v| puts_val k, "=", v }.any? or puts_val "(none)"
|
353
|
+
puts "block:"
|
354
|
+
@block.each_line { |l| puts_val l }
|
355
|
+
end
|
356
|
+
|
357
|
+
INDENT = " "*2
|
358
|
+
|
359
|
+
def puts_val *args
|
360
|
+
l = [ INDENT, *args].join ""
|
361
|
+
puts l
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
365
|
+
|
366
|
+
|
367
|
+
class Entry
|
368
|
+
|
369
|
+
# Alias the question marks away from all method names because
|
370
|
+
# they're a nuisance on the command line.
|
371
|
+
alias hidden hidden?
|
372
|
+
alias visible visible?
|
373
|
+
alias broken_link broken_link?
|
374
|
+
alias dir dir?
|
375
|
+
alias binary binary?
|
376
|
+
alias bin bin?
|
377
|
+
alias vimswap vimswap?
|
378
|
+
|
379
|
+
def blockdev ; blockdev? ; end
|
380
|
+
def chardev ; chardev? ; end
|
381
|
+
def directory ; directory? ; end
|
382
|
+
def executable ; executable? ; end
|
383
|
+
def executable_real ; executable_real? ; end
|
384
|
+
def file ; file? ; end
|
385
|
+
def grpowned ; grpowned? ; end
|
386
|
+
def owned ; owned? ; end
|
387
|
+
def pipe ; pipe? ; end
|
388
|
+
def readable ; readable? ; end
|
389
|
+
def readable_real ; readable_real? ; end
|
390
|
+
def setgid ; setgid? ; end
|
391
|
+
def setuid ; setuid? ; end
|
392
|
+
def socket ; socket? ; end
|
393
|
+
def sticky ; sticky? ; end
|
394
|
+
def symlink ; symlink? ; end
|
395
|
+
def writable ; writable? ; end
|
396
|
+
def writable_real ; writable_real? ; end
|
397
|
+
def zero ; zero? ; end
|
398
|
+
|
399
|
+
# convenient digest and time format methods
|
400
|
+
alias method_missing_orig method_missing
|
401
|
+
def method_missing sym, *args, &block
|
402
|
+
case sym.to_s
|
403
|
+
when /\Adigest_(.*)/, /\A([a-z]+[0-9]+)\z/ then
|
404
|
+
m = $1
|
405
|
+
d = begin
|
406
|
+
Digest.const_get m.upcase
|
407
|
+
rescue NameError
|
408
|
+
if m =~ /sha\d\d\d/ then m = "sha2" end
|
409
|
+
require "digest/#{m}" and retry
|
410
|
+
raise
|
411
|
+
end
|
412
|
+
e = d.new
|
413
|
+
read 0x1000_0000 do |b| e.update b end
|
414
|
+
e.hexdigest
|
415
|
+
when /\A([amc]time)!\z/ then
|
416
|
+
(send $1).strftime "%Y-%m-%d %H:%M:%S %z"
|
417
|
+
else
|
418
|
+
method_missing_orig sym, *args, &block
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|
423
|
+
|
424
|
+
end
|
139
425
|
|
140
426
|
|
141
427
|
class Time
|
@@ -176,9 +462,6 @@ class String
|
|
176
462
|
else super
|
177
463
|
end
|
178
464
|
end
|
179
|
-
def | width
|
180
|
-
ljust width
|
181
|
-
end
|
182
465
|
# conventient date/time construction
|
183
466
|
def time
|
184
467
|
Time.parse self
|
@@ -201,298 +484,12 @@ class NilClass
|
|
201
484
|
end
|
202
485
|
end
|
203
486
|
|
204
|
-
|
205
|
-
def
|
206
|
-
|
207
|
-
Encoding.default_internal = intern if intern and not intern.empty?
|
208
|
-
[ $stdin, $stdout, $stderr].each do |io|
|
209
|
-
io.set_encoding extern, intern
|
487
|
+
class Proc
|
488
|
+
def to_s
|
489
|
+
"#<%s:0x%08x>" % [ self.class, object_id]
|
210
490
|
end
|
211
491
|
end
|
212
492
|
|
213
493
|
|
214
|
-
|
215
|
-
|
216
|
-
# Alias the question marks away from all method names because
|
217
|
-
# they're a nuisance on the command line.
|
218
|
-
alias hidden hidden?
|
219
|
-
alias visible visible?
|
220
|
-
alias broken_link broken_link?
|
221
|
-
alias dir dir?
|
222
|
-
alias binary binary?
|
223
|
-
alias bin bin?
|
224
|
-
alias vimswap vimswap?
|
225
|
-
|
226
|
-
def blockdev ; blockdev? ; end
|
227
|
-
def chardev ; chardev? ; end
|
228
|
-
def directory ; directory? ; end
|
229
|
-
def executable ; executable? ; end
|
230
|
-
def executable_real ; executable_real? ; end
|
231
|
-
def file ; file? ; end
|
232
|
-
def grpowned ; grpowned? ; end
|
233
|
-
def owned ; owned? ; end
|
234
|
-
def pipe ; pipe? ; end
|
235
|
-
def readable ; readable? ; end
|
236
|
-
def readable_real ; readable_real? ; end
|
237
|
-
def setgid ; setgid? ; end
|
238
|
-
def setuid ; setuid? ; end
|
239
|
-
def socket ; socket? ; end
|
240
|
-
def sticky ; sticky? ; end
|
241
|
-
def symlink ; symlink? ; end
|
242
|
-
def writable ; writable? ; end
|
243
|
-
def writable_real ; writable_real? ; end
|
244
|
-
def zero ; zero? ; end
|
245
|
-
|
246
|
-
# convenient digest and time format methods
|
247
|
-
def method_missing sym, *args, &block
|
248
|
-
case sym.to_s
|
249
|
-
when /\Adigest_(.*)/, /\A([a-z]+[0-9]+)\z/ then
|
250
|
-
m = $1
|
251
|
-
d = begin
|
252
|
-
Digest.const_get m.upcase
|
253
|
-
rescue NameError
|
254
|
-
if m =~ /sha\d\d\d/ then m = "sha2" end
|
255
|
-
require "digest/#{m}" and retry
|
256
|
-
raise
|
257
|
-
end
|
258
|
-
e = d.new
|
259
|
-
read 0x1000_0000 do |b| e.update b end
|
260
|
-
e.hexdigest
|
261
|
-
when /\A([amc]time)!\z/ then
|
262
|
-
(send $1).strftime "%Y-%m-%d %H:%M:%S %z"
|
263
|
-
else
|
264
|
-
super
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def hide_instance_eval
|
269
|
-
instance_eval yield
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
|
275
|
-
@params = {}
|
276
|
-
|
277
|
-
envopts = ENV[ "RBFIND_OPTIONS"]
|
278
|
-
$*.unshift *envopts.split if envopts
|
279
|
-
opts = GetoptLong.new *OPTIONS.map { |(long,short),arg,|
|
280
|
-
[long,short,(arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT)]
|
281
|
-
}
|
282
|
-
opts.ordering = GetoptLong::PERMUTE
|
283
|
-
opts.quiet = true
|
284
|
-
begin
|
285
|
-
opts.each do |opt,arg|
|
286
|
-
case opt
|
287
|
-
when '--help' then usage ; exit
|
288
|
-
when '--version' then puts PROGRAM ; exit
|
289
|
-
when '--examples' then usage_examples ; exit
|
290
|
-
when '--verbose' then @verbose = true
|
291
|
-
when '--show' then @show = true
|
292
|
-
when '--bw' then @color = false
|
293
|
-
when '--colored' then @color = true
|
294
|
-
when '--depth' then @params[ :depth] = true
|
295
|
-
when '--maxdepth' then @params[ :max_depth] = arg
|
296
|
-
when '--follow' then @params[ :follow] = true
|
297
|
-
when '--sort' then @params[ :sort] = arg
|
298
|
-
when '--sort-by' then
|
299
|
-
@params[ :sort] = instance_eval "proc { |name| #{arg} }"
|
300
|
-
when '--require' then require arg
|
301
|
-
when '--fileutils' then require "fileutils" ; include FileUtils
|
302
|
-
when '--puts-path' then @puts = true
|
303
|
-
when '--ls-l' then @puts = true ; @wd = 6
|
304
|
-
when '--wider' then @wd = @wd ? @wd.succ : 4
|
305
|
-
when '--slash' then @slash = true
|
306
|
-
when '--lines' then @lines = :plain ; @block = arg
|
307
|
-
when '--reallines' then @lines = :plain ; @real = true ; @block = arg
|
308
|
-
when '--grep' then @lines = :grep ; @block = arg
|
309
|
-
when '--igrep' then @lines = :grep ; @icase = true ; @block = arg
|
310
|
-
when '--binary' then @binary = true
|
311
|
-
when '--no-vcs' then @vcs = true
|
312
|
-
when '--no-swap' then @vim = true
|
313
|
-
when '--skip' then @skip = arg
|
314
|
-
when '--demand' then @demand = arg
|
315
|
-
when '--ext' then @ext = arg
|
316
|
-
when '--visible' then @visible = true
|
317
|
-
when '--nodirs' then @nodirs = true
|
318
|
-
when '--begin' then @blkbegin = arg
|
319
|
-
when '--end' then @blkend = arg
|
320
|
-
when '--file' then @block = File.read arg
|
321
|
-
when '--encoding' then e, i = arg.split ":" ; set_encoding e, i
|
322
|
-
end
|
323
|
-
end
|
324
|
-
rescue GetoptLong::InvalidOption
|
325
|
-
$stderr.puts $!
|
326
|
-
$stderr.puts
|
327
|
-
usage
|
328
|
-
exit 9
|
329
|
-
rescue
|
330
|
-
$stderr.puts $!
|
331
|
-
exit 8
|
332
|
-
end
|
333
|
-
|
334
|
-
def color_on stream
|
335
|
-
unless @color.nil? then
|
336
|
-
@color
|
337
|
-
else
|
338
|
-
!File::ALT_SEPARATOR && stream.tty?
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
if color_on $stderr then
|
343
|
-
def show_error e
|
344
|
-
$stderr.puts "\e[31m#{e.class}: \e[1m#{e}\e[m"
|
345
|
-
end
|
346
|
-
else
|
347
|
-
def show_error e
|
348
|
-
$stderr.puts "#{e.class}: #{e}"
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
def error_handle
|
353
|
-
if @verbose then
|
354
|
-
yield
|
355
|
-
else
|
356
|
-
begin
|
357
|
-
yield
|
358
|
-
rescue ArgumentError
|
359
|
-
show_error $!
|
360
|
-
if $!.message[ "invalid byte sequence"] then
|
361
|
-
$stderr.puts <<-EOT
|
362
|
-
Hint: Try to give a different default encoding by explicitly setting one or
|
363
|
-
by changing the locale.
|
364
|
-
|
365
|
-
$ rbfind -K ascii-8bit ...
|
366
|
-
$ LC_ALL="C" rbfind ...
|
367
|
-
|
368
|
-
Alternatively, you may prefer to scrub the invalid encodings yourself.
|
369
|
-
|
370
|
-
$ rbfind -P 'name.scrub =~ /Fu.ball/'
|
371
|
-
|
372
|
-
EOT
|
373
|
-
end
|
374
|
-
exit 1
|
375
|
-
rescue
|
376
|
-
show_error $!
|
377
|
-
exit 1
|
378
|
-
rescue NoMemoryError, ScriptError, SignalException
|
379
|
-
show_error $!
|
380
|
-
exit 2
|
381
|
-
end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
|
386
|
-
error_handle do
|
387
|
-
|
388
|
-
co = color_on $stdout
|
389
|
-
opath = co ? "cpath" : "path"
|
390
|
-
@slash and opath << "!"
|
391
|
-
case @lines
|
392
|
-
when :plain then
|
393
|
-
@puts and @block = "( #@block ) and colsep #{opath}, num, line"
|
394
|
-
@real and @block = "break if ~/\0/o ; #@block"
|
395
|
-
@block = "lines { |line,num| #@block }"
|
396
|
-
|
397
|
-
when :grep then
|
398
|
-
RE = Regexp.new @block, @icase && Regexp::IGNORECASE
|
399
|
-
@block = "grep RE"
|
400
|
-
@block << ", true" if co
|
401
|
-
@block << " ; $stdout.flush" unless $stdout.tty?
|
402
|
-
@binary or @block = "not binary? and (#@block)"
|
403
|
-
|
404
|
-
else
|
405
|
-
@block ||= if $*.last and not (File.exists? $*.last) then
|
406
|
-
$*.pop.dup
|
407
|
-
else
|
408
|
-
@puts ||= true
|
409
|
-
"true"
|
410
|
-
end
|
411
|
-
if @puts then
|
412
|
-
@block = "( #@block ) and "
|
413
|
-
@block << if @wd then
|
414
|
-
"spcsep stype+modes, user|#@wd, group|#@wd, size.w#@wd, " +
|
415
|
-
"mtime.lsish, #{opath} + #{co ? 'carrow' : 'arrow'}.to_s"
|
416
|
-
else
|
417
|
-
"puts #{opath}"
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
end
|
422
|
-
|
423
|
-
if @skip then
|
424
|
-
RE_SKIP = Regexp.new @skip, File::ALT_SEPARATOR&&Regexp::IGNORECASE
|
425
|
-
@block.insert 0, "next if name =~ RE_SKIP ; "
|
426
|
-
end
|
427
|
-
|
428
|
-
if @demand then
|
429
|
-
RE_DEMAND = Regexp.new @demand, File::ALT_SEPARATOR&&Regexp::IGNORECASE
|
430
|
-
@block.insert 0, "next unless name =~ RE_DEMAND ; "
|
431
|
-
end
|
432
|
-
|
433
|
-
if @ext then
|
434
|
-
RE_EXT = Regexp.new '\A\.(' +
|
435
|
-
@ext.split(/ +|,/).map { |e| e[ /\A\.?(.*)\z/, 1] }.join('|') + ')\z',
|
436
|
-
File::ALT_SEPARATOR&&Regexp::IGNORECASE
|
437
|
-
@block.insert 0, "ext =~ RE_EXT or next ; "
|
438
|
-
end
|
439
|
-
|
440
|
-
@visible and @block.insert 0, "visible? or prune ; "
|
441
|
-
|
442
|
-
@nodirs and @block.insert 0, "next if dir? ; "
|
443
|
-
|
444
|
-
@vcs and @block.insert 0, "no_vcs ; "
|
445
|
-
@vim and @block.insert 0, "vimswap? and next ; "
|
446
|
-
|
447
|
-
args = $*.dup
|
448
|
-
if args.empty? and not $stdin.tty? then
|
449
|
-
$stdin.each_line { |l|
|
450
|
-
l.chomp!
|
451
|
-
args.push l
|
452
|
-
}
|
453
|
-
end
|
454
|
-
|
455
|
-
if @show then
|
456
|
-
class Proc
|
457
|
-
def to_s
|
458
|
-
"#<%s:0x%08x>" % [ self.class, object_id]
|
459
|
-
end
|
460
|
-
end
|
461
|
-
INDENT = " "*2
|
462
|
-
def puts_val *args
|
463
|
-
l = [ INDENT, *args].join ""
|
464
|
-
puts l
|
465
|
-
end
|
466
|
-
puts "arguments:"
|
467
|
-
args.each { |a| puts_val a }.any? or puts_val "(none)"
|
468
|
-
puts "parameters:"
|
469
|
-
@params.each { |k,v| puts_val k, "=", v }.any? or puts_val "(none)"
|
470
|
-
puts "block:"
|
471
|
-
self.class.constants.grep( /^RE(_[A-Z]+)?$/).each { |re|
|
472
|
-
v = self.class.const_get re
|
473
|
-
puts_val re, "=", v
|
474
|
-
}
|
475
|
-
puts_val @block
|
476
|
-
exit
|
477
|
-
end
|
478
|
-
|
479
|
-
@params[ :error] = proc do
|
480
|
-
case $!
|
481
|
-
when Errno::EPIPE then raise
|
482
|
-
when NameError, TypeError then raise
|
483
|
-
when ArgumentError then raise
|
484
|
-
else show_error $!
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
@block = <<-EOT
|
489
|
-
handle_error do
|
490
|
-
#@block
|
491
|
-
end
|
492
|
-
EOT
|
493
|
-
|
494
|
-
eval @blkbegin if @blkbegin
|
495
|
-
RbFindApp.open args, @params do |f| f.hide_instance_eval { @block } end
|
496
|
-
eval @blkend if @blkend
|
497
|
-
end
|
494
|
+
RbFind::Application.new.run
|
498
495
|
|