minitar-cli 0.6
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 +7 -0
- data/Contributing.md +71 -0
- data/History.md +25 -0
- data/Licence.md +15 -0
- data/Manifest.txt +22 -0
- data/README.rdoc +105 -0
- data/Rakefile +47 -0
- data/bin/minitar +11 -0
- data/docs/bsdl.txt +19 -0
- data/docs/ruby.txt +56 -0
- data/lib/minitar/cli.rb +64 -0
- data/lib/minitar/cli/command.rb +46 -0
- data/lib/minitar/cli/command/create.rb +144 -0
- data/lib/minitar/cli/command/extract.rb +174 -0
- data/lib/minitar/cli/command/help.rb +57 -0
- data/lib/minitar/cli/command/list.rb +162 -0
- data/lib/minitar/cli/commander.rb +64 -0
- data/test/fixtures/bad-dir.tar.gz +0 -0
- data/test/fixtures/spaces.tar.gz +0 -0
- data/test/minitest_helper.rb +11 -0
- data/test/support/minitar_cli_test_helper.rb +15 -0
- data/test/test_cli_help.rb +71 -0
- data/test/test_cli_list.rb +123 -0
- metadata +265 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The base for commands in Minitar::CLI. This will be replaced in a future
|
4
|
+
# version by one of the better-executed CLI application frameworks like GLI,
|
5
|
+
# after Ruby 1.8 and 1.9 support have been dropped.
|
6
|
+
class Minitar::CLI::Command
|
7
|
+
@children = []
|
8
|
+
|
9
|
+
attr_reader :commander
|
10
|
+
attr_reader :ioe
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :children
|
14
|
+
|
15
|
+
def inherited(subclass)
|
16
|
+
children << subclass
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module CatchMinitarErrors # :nodoc:
|
21
|
+
def call(args, opts)
|
22
|
+
run(args, opts)
|
23
|
+
rescue Archive::Tar::Minitar::Error => error
|
24
|
+
ioe[:error] << "#{error}\n"
|
25
|
+
5
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(commander)
|
30
|
+
@commander = commander
|
31
|
+
@ioe = commander.ioe
|
32
|
+
end
|
33
|
+
|
34
|
+
def name
|
35
|
+
raise Minitar::CLI::AbstractCommandError
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(_args, _opts = {})
|
39
|
+
raise Minitar::CLI::AbstractCommandError
|
40
|
+
end
|
41
|
+
alias [] call
|
42
|
+
|
43
|
+
def help
|
44
|
+
raise Minitar::CLI::AbstractCommandError
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Tarball creation command. This will be replaced in a future version by one of
|
4
|
+
# the better-executed CLI application frameworks like GLI, after Ruby 1.8 and
|
5
|
+
# 1.9 support have been dropped.
|
6
|
+
class Minitar::CLI::Command::Create < Minitar::CLI::Command
|
7
|
+
def name
|
8
|
+
'create'
|
9
|
+
end
|
10
|
+
|
11
|
+
def altname
|
12
|
+
'cr'
|
13
|
+
end
|
14
|
+
|
15
|
+
HELP = <<-EOH.freeze
|
16
|
+
minitar create [OPTIONS] <tarfile|-> <file|directory|-->+
|
17
|
+
|
18
|
+
Creates a new tarfile. If the tarfile is named .tar.gz or .tgz, then it
|
19
|
+
will be compressed automatically. If the tarfile is "-", then it will be
|
20
|
+
output to standard output (stdout) so that minitar may be piped.
|
21
|
+
|
22
|
+
The files or directories that will be packed into the tarfile are
|
23
|
+
specified after the name of the tarfile itself. Directories will be
|
24
|
+
processed recursively. If the token "--" is found in the list of files
|
25
|
+
to be packed, additional filenames will be read from standard input
|
26
|
+
(stdin). If any file is not found, the packaging will be halted.
|
27
|
+
|
28
|
+
create Options:
|
29
|
+
--compress, -z Compresses the tarfile with gzip.
|
30
|
+
|
31
|
+
EOH
|
32
|
+
|
33
|
+
include CatchMinitarErrors
|
34
|
+
|
35
|
+
def run(args, opts = {})
|
36
|
+
argv = []
|
37
|
+
|
38
|
+
while (arg = args.shift)
|
39
|
+
case arg
|
40
|
+
when '--compress', '-z'
|
41
|
+
opts[:compress] = true
|
42
|
+
else
|
43
|
+
argv << arg
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if argv.size < 2
|
48
|
+
ioe[:output] << "Not enough arguments.\n\n"
|
49
|
+
commander.command('help').call(%w(create))
|
50
|
+
return 255
|
51
|
+
end
|
52
|
+
|
53
|
+
output = argv.shift
|
54
|
+
if '-' == output
|
55
|
+
opts[:name] = 'STDOUT'
|
56
|
+
output = ioe[:output]
|
57
|
+
opts[:output] = ioe[:error]
|
58
|
+
else
|
59
|
+
opts[:name] = output
|
60
|
+
output = File.open(output, 'wb')
|
61
|
+
opts[:output] = ioe[:output]
|
62
|
+
end
|
63
|
+
|
64
|
+
if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:compress]
|
65
|
+
output = Zlib::GzipWriter.new(output)
|
66
|
+
end
|
67
|
+
|
68
|
+
files = []
|
69
|
+
if argv.include?('--')
|
70
|
+
# Read stdin for the list of files.
|
71
|
+
files = ''
|
72
|
+
files << ioe[:input].read until ioe[:input].eof?
|
73
|
+
files = files.split(/\r\n|\n|\r/)
|
74
|
+
args.delete('--')
|
75
|
+
end
|
76
|
+
|
77
|
+
files << argv.to_a
|
78
|
+
files.flatten!
|
79
|
+
|
80
|
+
watcher, finisher =
|
81
|
+
if opts[:verbose]
|
82
|
+
verbose
|
83
|
+
elsif opts[:progress]
|
84
|
+
progress
|
85
|
+
else
|
86
|
+
silent
|
87
|
+
end
|
88
|
+
|
89
|
+
Archive::Tar::Minitar.pack(files, output, &watcher)
|
90
|
+
finisher.call
|
91
|
+
0
|
92
|
+
ensure
|
93
|
+
output.close if output && !output.closed?
|
94
|
+
end
|
95
|
+
|
96
|
+
def help
|
97
|
+
HELP
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def verbose
|
103
|
+
[
|
104
|
+
lambda { |action, name, _stats|
|
105
|
+
opts[:output] << "#{name}\n" if action == :dir || action == :file_done
|
106
|
+
},
|
107
|
+
lambda { opts[:output] << "\n" }
|
108
|
+
]
|
109
|
+
end
|
110
|
+
|
111
|
+
def progress
|
112
|
+
require 'powerbar'
|
113
|
+
progress = PowerBar.new(:msg => opts[:name], :total => 1)
|
114
|
+
[
|
115
|
+
lambda { |action, name, stats|
|
116
|
+
progress_info = {}
|
117
|
+
|
118
|
+
case action
|
119
|
+
when :file_start, :dir
|
120
|
+
progress_info[:msg] = File.basename(name)
|
121
|
+
|
122
|
+
if action == :dir
|
123
|
+
progress_info[:total] = progress.total + 1
|
124
|
+
progress_info[:done] = progress.done + 1
|
125
|
+
else
|
126
|
+
progress_info[:total] = progress.total + stats[:size]
|
127
|
+
end
|
128
|
+
when :file_progress
|
129
|
+
progress_info[:done] = progress.done + stats[:currinc]
|
130
|
+
end
|
131
|
+
|
132
|
+
progress.show(progress_info)
|
133
|
+
},
|
134
|
+
lambda {
|
135
|
+
progress.show(:msg => opts[:name])
|
136
|
+
progress.close(true)
|
137
|
+
}
|
138
|
+
]
|
139
|
+
end
|
140
|
+
|
141
|
+
def silent
|
142
|
+
[ lambda { |_, _, _| }, lambda {} ]
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Tarball extraction command. This will be replaced in a future version by one
|
4
|
+
# of the better-executed CLI application frameworks like GLI, after Ruby 1.8
|
5
|
+
# and 1.9 support have been dropped.
|
6
|
+
class Minitar::CLI::Command::Extract < Minitar::CLI::Command
|
7
|
+
def name
|
8
|
+
'extract'
|
9
|
+
end
|
10
|
+
|
11
|
+
def altname
|
12
|
+
'ex'
|
13
|
+
end
|
14
|
+
|
15
|
+
HELP = <<-EOH.freeze
|
16
|
+
minitar extract [OPTIONS] <tarfile|-> [<file>+]
|
17
|
+
|
18
|
+
Extracts files from an existing tarfile. If the tarfile is named .tar.gz
|
19
|
+
or .tgz, then it will be uncompressed automatically. If the tarfile is
|
20
|
+
"-", then it will be read from standard input (stdin) so that minitar
|
21
|
+
may be piped.
|
22
|
+
|
23
|
+
The files or directories that will be extracted from the tarfile are
|
24
|
+
specified after the name of the tarfile itself. Directories will be
|
25
|
+
processed recursively. Files must be specified in full. A file
|
26
|
+
"foo/bar/baz.txt" cannot simply be specified by specifying "baz.txt".
|
27
|
+
Any file not found will simply be skipped and an error will be reported.
|
28
|
+
|
29
|
+
extract Options:
|
30
|
+
--uncompress, -z Uncompresses the tarfile with gzip.
|
31
|
+
--pipe Emits the extracted files to STDOUT for piping.
|
32
|
+
--output, -o Extracts the files to the specified directory.
|
33
|
+
|
34
|
+
EOH
|
35
|
+
|
36
|
+
include CatchMinitarErrors
|
37
|
+
|
38
|
+
def run(args, opts = {})
|
39
|
+
argv = []
|
40
|
+
output = nil
|
41
|
+
dest = '.'
|
42
|
+
files = []
|
43
|
+
|
44
|
+
while (arg = args.shift)
|
45
|
+
case arg
|
46
|
+
when '--uncompress', '-z'
|
47
|
+
opts[:uncompress] = true
|
48
|
+
when '--pipe'
|
49
|
+
output = ioe[:output]
|
50
|
+
ioe[:output] = ioe[:error]
|
51
|
+
when '--output', '-o'
|
52
|
+
dest = args.shift
|
53
|
+
else
|
54
|
+
argv << arg
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
if argv.empty?
|
59
|
+
ioe[:output] << "Not enough arguments.\n\n"
|
60
|
+
commander.command('help').call(%w(extract))
|
61
|
+
return 255
|
62
|
+
end
|
63
|
+
|
64
|
+
input = argv.shift
|
65
|
+
if '-' == input
|
66
|
+
opts[:name] = 'STDIN'
|
67
|
+
input = ioe[:input]
|
68
|
+
else
|
69
|
+
opts[:name] = input
|
70
|
+
input = File.open(input, 'rb')
|
71
|
+
end
|
72
|
+
|
73
|
+
if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress]
|
74
|
+
input = Zlib::GzipReader.new(input)
|
75
|
+
end
|
76
|
+
|
77
|
+
files << argv.to_a
|
78
|
+
files.flatten!
|
79
|
+
|
80
|
+
watcher, finisher =
|
81
|
+
if opts[:verbose]
|
82
|
+
verbose
|
83
|
+
elsif opts[:progress]
|
84
|
+
progress
|
85
|
+
else
|
86
|
+
silent
|
87
|
+
end
|
88
|
+
|
89
|
+
if output.nil?
|
90
|
+
Archive::Tar::Minitar.unpack(input, dest, files, &watcher)
|
91
|
+
finisher.call
|
92
|
+
else
|
93
|
+
Archive::Tar::Minitar::Input.each_entry(input) do |entry|
|
94
|
+
next unless files.empty? || files.include?(entry.full_name)
|
95
|
+
|
96
|
+
stats = {
|
97
|
+
:mode => entry.mode,
|
98
|
+
:mtime => entry.mtime,
|
99
|
+
:size => entry.size,
|
100
|
+
:gid => entry.gid,
|
101
|
+
:uid => entry.uid,
|
102
|
+
:current => 0,
|
103
|
+
:currinc => 0,
|
104
|
+
:entry => entry
|
105
|
+
}
|
106
|
+
|
107
|
+
if entry.directory?
|
108
|
+
watcher.call(:dir, dest, stats)
|
109
|
+
else
|
110
|
+
watcher.call(:file_start, destfile, stats)
|
111
|
+
loop do
|
112
|
+
data = entry.read(4096)
|
113
|
+
break unless data
|
114
|
+
stats[:currinc] = output.write(data)
|
115
|
+
stats[:current] += stats[:currinc]
|
116
|
+
|
117
|
+
watcher.call(:file_progress, name, stats)
|
118
|
+
end
|
119
|
+
watcher.call(:file_done, name, stats)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
0
|
125
|
+
end
|
126
|
+
|
127
|
+
def help
|
128
|
+
HELP
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def verbose
|
134
|
+
[
|
135
|
+
lambda { |action, name, _stats|
|
136
|
+
ioe[:output] << "#{name}\n" if action == :dir or action == :file_done
|
137
|
+
},
|
138
|
+
lambda { ioe[:output] << "\n" }
|
139
|
+
]
|
140
|
+
end
|
141
|
+
|
142
|
+
def progress
|
143
|
+
require 'powerbar'
|
144
|
+
progress = PowerBar.new(:msg => opts[:name], :total => 1)
|
145
|
+
[
|
146
|
+
lambda { |action, name, stats|
|
147
|
+
progress_info = {}
|
148
|
+
|
149
|
+
case action
|
150
|
+
when :file_start, :dir
|
151
|
+
progress_info[:msg] = File.basename(name)
|
152
|
+
if action == :dir
|
153
|
+
progress_info[:total] = progress.total + 1
|
154
|
+
progress_info[:done] = progress.done + 1
|
155
|
+
else
|
156
|
+
progress_info[:total] = progress.total + stats[:entry].size
|
157
|
+
end
|
158
|
+
when :file_progress
|
159
|
+
progress_info[:done] = progress.done + stats[:currinc]
|
160
|
+
end
|
161
|
+
|
162
|
+
progress.show(progress_info)
|
163
|
+
},
|
164
|
+
lambda {
|
165
|
+
progress.show(:msg => opts[:name])
|
166
|
+
progress.close(true)
|
167
|
+
}
|
168
|
+
]
|
169
|
+
end
|
170
|
+
|
171
|
+
def silent
|
172
|
+
[ lambda { |_, _, _| }, lambda {} ]
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Help command. This will be replaced in a future version by one of the
|
4
|
+
# better-executed CLI application frameworks like GLI, after Ruby 1.8 and 1.9
|
5
|
+
# support have been dropped.
|
6
|
+
class Minitar::CLI::Command::Help < Minitar::CLI::Command
|
7
|
+
def name
|
8
|
+
'help'
|
9
|
+
end
|
10
|
+
|
11
|
+
COMMANDS = <<-EOS.freeze
|
12
|
+
The commands known to minitar are:
|
13
|
+
|
14
|
+
minitar create Creates a new tarfile.
|
15
|
+
minitar extract Extracts files from a tarfile.
|
16
|
+
minitar list Lists files in the tarfile.
|
17
|
+
|
18
|
+
All commands accept the options --verbose and --progress, which are
|
19
|
+
mutually exclusive. In "minitar list", --progress means the same as
|
20
|
+
--verbose.
|
21
|
+
|
22
|
+
--verbose, -V Performs the requested command verbosely.
|
23
|
+
--progress, -P Shows a progress bar, if appropriate, for the action
|
24
|
+
being performed.
|
25
|
+
|
26
|
+
EOS
|
27
|
+
|
28
|
+
BASIC = <<-EOS.freeze
|
29
|
+
This is a basic help message containing pointers to more information on
|
30
|
+
how to use this command-line tool. Try:
|
31
|
+
|
32
|
+
minitar help commands list all 'minitar' commands
|
33
|
+
minitar help <COMMAND> show help on <COMMAND>
|
34
|
+
(e.g., 'minitar help create')
|
35
|
+
EOS
|
36
|
+
|
37
|
+
def call(args, _opts = {})
|
38
|
+
help_on = args.shift
|
39
|
+
|
40
|
+
if commander.command?(help_on)
|
41
|
+
ioe[:output] << commander[help_on].help
|
42
|
+
elsif help_on == 'commands'
|
43
|
+
ioe[:output] << COMMANDS
|
44
|
+
else
|
45
|
+
unless help_on.nil? or help_on.empty?
|
46
|
+
ioe[:output] << "Unknown command: #{help_on}\n"
|
47
|
+
end
|
48
|
+
ioe[:output] << help
|
49
|
+
end
|
50
|
+
|
51
|
+
0
|
52
|
+
end
|
53
|
+
|
54
|
+
def help
|
55
|
+
BASIC
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Tarball list command. This will be replaced in a future version by one of the
|
4
|
+
# better-executed CLI application frameworks like GLI, after Ruby 1.8 and 1.9
|
5
|
+
# support have been dropped.
|
6
|
+
class Minitar::CLI::Command::List < Minitar::CLI::Command
|
7
|
+
def name
|
8
|
+
'list'
|
9
|
+
end
|
10
|
+
|
11
|
+
def altname
|
12
|
+
'ls'
|
13
|
+
end
|
14
|
+
|
15
|
+
HELP = <<-EOH.freeze
|
16
|
+
minitar list [OPTIONS] <tarfile|-> [<file>+]
|
17
|
+
|
18
|
+
Lists files in an existing tarfile. If the tarfile is named .tar.gz or
|
19
|
+
.tgz, then it will be uncompressed automatically. If the tarfile is "-",
|
20
|
+
then it will be read from standard input (stdin) so that minitar may be
|
21
|
+
piped.
|
22
|
+
|
23
|
+
If --verbose or --progress is specified, then the file list will be
|
24
|
+
similar to that produced by the Unix command "ls -l".
|
25
|
+
|
26
|
+
list Options:
|
27
|
+
--uncompress, -z Uncompresses the tarfile with gzip.
|
28
|
+
--sort [<FIELD>], -S Sorts the list of files by the specified
|
29
|
+
field. The sort defaults to the filename.
|
30
|
+
--reverse, -R Reverses the sort.
|
31
|
+
-l Lists the files in detail.
|
32
|
+
|
33
|
+
Sort Fields:
|
34
|
+
name, mtime, size
|
35
|
+
|
36
|
+
EOH
|
37
|
+
|
38
|
+
def modestr(mode)
|
39
|
+
s = String.new('---')
|
40
|
+
s[0] = 'r' if (mode & 4) == 4
|
41
|
+
s[1] = 'w' if (mode & 2) == 2
|
42
|
+
s[2] = 'x' if (mode & 1) == 1
|
43
|
+
s
|
44
|
+
end
|
45
|
+
|
46
|
+
include CatchMinitarErrors
|
47
|
+
|
48
|
+
def run(args, opts = {})
|
49
|
+
argv = []
|
50
|
+
output = nil
|
51
|
+
files = []
|
52
|
+
opts[:field] = 'name'
|
53
|
+
|
54
|
+
while (arg = args.shift)
|
55
|
+
case arg
|
56
|
+
when '--sort', '-S'
|
57
|
+
opts[:sort] = true
|
58
|
+
opts[:field] = args.shift
|
59
|
+
when '--reverse', '-R'
|
60
|
+
opts[:reverse] = true
|
61
|
+
opts[:sort] = true
|
62
|
+
when '--uncompress', '-z'
|
63
|
+
opts[:uncompress] = true
|
64
|
+
when '-l'
|
65
|
+
opts[:verbose] = true
|
66
|
+
else
|
67
|
+
argv << arg
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if argv.empty?
|
72
|
+
ioe[:output] << "Not enough arguments.\n\n"
|
73
|
+
commander.command('help').call(%w(list))
|
74
|
+
return 255
|
75
|
+
end
|
76
|
+
|
77
|
+
input = argv.shift
|
78
|
+
if '-' == input
|
79
|
+
opts[:name] = 'STDIN'
|
80
|
+
input = ioe[:input]
|
81
|
+
else
|
82
|
+
opts[:name] = input
|
83
|
+
input = File.open(input, 'rb')
|
84
|
+
end
|
85
|
+
|
86
|
+
if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress]
|
87
|
+
input = Zlib::GzipReader.new(input)
|
88
|
+
end
|
89
|
+
|
90
|
+
files << argv.to_a
|
91
|
+
files.flatten!
|
92
|
+
|
93
|
+
if opts[:verbose] or opts[:progress]
|
94
|
+
format = '%10s %4d %8s %8s %8d %12s %s'
|
95
|
+
datefmt = '%b %d %Y'
|
96
|
+
timefmt = '%b %d %H:%M'
|
97
|
+
fields = %w(permissions inodes user group size date fullname)
|
98
|
+
else
|
99
|
+
format = '%s'
|
100
|
+
fields = %w(fullname)
|
101
|
+
end
|
102
|
+
|
103
|
+
opts[:field] = opts[:field].to_sym
|
104
|
+
opts[:field] = :full_name if opts[:field] == :name
|
105
|
+
|
106
|
+
output = []
|
107
|
+
|
108
|
+
today = Time.now
|
109
|
+
oneyear = Time.mktime(today.year - 1, today.month, today.day)
|
110
|
+
|
111
|
+
Archive::Tar::Minitar::Input.each_entry(input) do |entry|
|
112
|
+
next unless files.empty? || files.include?(entry.full_name)
|
113
|
+
|
114
|
+
value = format % fields.map { |ff|
|
115
|
+
case ff
|
116
|
+
when 'permissions'
|
117
|
+
s = String.new(entry.directory? ? 'd' : '-')
|
118
|
+
s << modestr(entry.mode / 0o100)
|
119
|
+
s << modestr(entry.mode / 0o010)
|
120
|
+
s << modestr(entry.mode)
|
121
|
+
when 'inodes'
|
122
|
+
entry.size / 512
|
123
|
+
when 'user'
|
124
|
+
entry.uname || entry.uid || 0
|
125
|
+
when 'group'
|
126
|
+
entry.gname || entry.gid || 0
|
127
|
+
when 'size'
|
128
|
+
entry.size
|
129
|
+
when 'date'
|
130
|
+
if Time.at(entry.mtime) > oneyear
|
131
|
+
Time.at(entry.mtime).strftime(timefmt)
|
132
|
+
else
|
133
|
+
Time.at(entry.mtime).strftime(datefmt)
|
134
|
+
end
|
135
|
+
when 'fullname'
|
136
|
+
entry.full_name
|
137
|
+
end
|
138
|
+
}
|
139
|
+
|
140
|
+
if opts[:sort]
|
141
|
+
output << [ entry.send(opts[:field]), value ]
|
142
|
+
else
|
143
|
+
ioe[:output] << value << "\n"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if opts[:sort]
|
148
|
+
output = output.sort { |a, b| a[0] <=> b[0] }
|
149
|
+
if opts[:reverse]
|
150
|
+
output.reverse_each { |oo| ioe[:output] << oo[1] << "\n" }
|
151
|
+
else
|
152
|
+
output.each { |oo| ioe[:output] << oo[1] << "\n" }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
0
|
157
|
+
end
|
158
|
+
|
159
|
+
def help
|
160
|
+
HELP
|
161
|
+
end
|
162
|
+
end
|