benry-unixcommand 1.0.0

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.
@@ -0,0 +1,932 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
6
+ <meta name="description" content="">
7
+ <meta name="theme-color" content="#fafafa">
8
+ <meta property="og:title" content="">
9
+ <meta property="og:type" content="">
10
+ <meta property="og:url" content="">
11
+ <meta property="og:image" content="">
12
+ <title></title>
13
+ <link rel="stylesheet" href="lib/sanitize.css/2.0.0/sanitize.min.css">
14
+ <link rel="stylesheet" href="css/style.css">
15
+ </head>
16
+ <body>
17
+ <main>
18
+ <section class="chapter" id="benry-unixcommand">
19
+ <h1>Benry-UnixCommand</h1>
20
+ <nav class="nav">
21
+ <ul class="nav">
22
+ </ul>
23
+ </nav>
24
+ <p>($Release: 1.0.0 $)</p>
25
+ <section class="section" id="whats-this">
26
+ <h2>What's this?</h2>
27
+ <p>Benry-UnixCommand implements popular UNIX commands, like FileUtils,
28
+ but much better than it.</p>
29
+ <ul>
30
+ <li>Document: <a href="https://kwatch.github.io/benry-ruby/benry-unixcommand.html">https://kwatch.github.io/benry-ruby/benry-unixcommand.html</a></li>
31
+ <li>GitHub: <a href="https://github.com/kwatch/benry-ruby/tree/main/benry-unixcommand">https://github.com/kwatch/benry-ruby/tree/main/benry-unixcommand</a></li>
32
+ <li>Changes: <a href="https://github.com/kwatch/benry-ruby/blob/main/benry-unixcommand/CHANGES.md">https://github.com/kwatch/benry-ruby/blob/main/benry-unixcommand/CHANGES.md</a></li>
33
+ </ul>
34
+ <p>Features compared to FileUtils:</p>
35
+ <ul>
36
+ <li>supports file patterns (<code>*</code>, <code>.</code>, <code>{}</code>) directly.</li>
37
+ <li>provides <code>cp :r</code>, <code>mv :p</code>, <code>rm :rf</code>, ... instead of <code>cp_r</code>, <code>mv_p</code>, <code>rm_rf</code>, ...</li>
38
+ <li>prints command prompt <code>$ </code> before command echoback.</li>
39
+ <li>provides <code>pushd</code> which is similar to <code>cd</code> but supports nested calls naturally.</li>
40
+ <li>implements <code>capture2</code>, <code>capture2e</code>, and <code>capture3</code> which calls
41
+ <code>Popen3.capture2</code>, <code>Popen3.capture2</code>, and <code>Popen3.capture3</code> respectively.</li>
42
+ <li>supports <code>touch -r reffile</code>.</li>
43
+ <li>provides <code>sys</code> command which is similar to <code>sh</code> in Rake but different in details.</li>
44
+ <li>provides <code>zip</code> and <code>unzip</code> commands (requires <code>rubyzip</code> gem).</li>
45
+ <li>provides <code>store</code> command which copies files recursively into target directory, keeping file path.</li>
46
+ <li>provides <code>atomic_symlink!</code> command which switches symlink atomically.</li>
47
+ </ul>
48
+ <p>(Benry-UnixCommand requires Ruby &gt;= 2.3)</p>
49
+ <section class="subsection" id="table-of-contents">
50
+ <h3>Table of Contents</h3>
51
+ <div class="toc">
52
+ <ul>
53
+ <li><a href="#whats-this">What's this?</a></li>
54
+ <li><a href="#install">Install</a></li>
55
+ <li><a href="#command-reference">Command Reference</a>
56
+ <ul>
57
+ <li><a href="#echo"><code>echo</code></a></li>
58
+ <li><a href="#echoback"><code>echoback</code></a></li>
59
+ <li><a href="#cp"><code>cp</code></a></li>
60
+ <li><a href="#mv"><code>mv</code></a></li>
61
+ <li><a href="#rm"><code>rm</code></a></li>
62
+ <li><a href="#mkdir"><code>mkdir</code></a></li>
63
+ <li><a href="#rmdir"><code>rmdir</code></a></li>
64
+ <li><a href="#ln"><code>ln</code></a></li>
65
+ <li><a href="#atomic_symlink"><code>atomic_symlink!</code></a></li>
66
+ <li><a href="#touch"><code>touch</code></a></li>
67
+ <li><a href="#chmod"><code>chmod</code></a></li>
68
+ <li><a href="#chown"><code>chown</code></a></li>
69
+ <li><a href="#pwd"><code>pwd</code></a></li>
70
+ <li><a href="#cd"><code>cd</code></a></li>
71
+ <li><a href="#pushd"><code>pushd</code></a></li>
72
+ <li><a href="#store"><code>store</code></a></li>
73
+ <li><a href="#sys"><code>sys</code></a></li>
74
+ <li><a href="#ruby"><code>ruby</code></a></li>
75
+ <li><a href="#capture2"><code>capture2</code></a></li>
76
+ <li><a href="#capture2e"><code>capture2e</code></a></li>
77
+ <li><a href="#capture3"><code>capture3</code></a></li>
78
+ <li><a href="#zip"><code>zip</code></a></li>
79
+ <li><a href="#unzip"><code>unzip</code></a></li>
80
+ <li><a href="#time"><code>time</code></a></li>
81
+ </ul></li>
82
+ <li><a href="#faq">FAQ</a>
83
+ <ul>
84
+ <li><a href="#why-mv-or-cp-requires-to-option">Why <code>mv</code> or <code>cp</code> requires <code>to:</code> option?</a></li>
85
+ <li><a href="#how-to-use-in-rakefile">How to use in Rakefile?</a></li>
86
+ <li><a href="#how-to-change-prompt-string">How to change prompt string?</a></li>
87
+ <li><a href="#how-to-make-prompt-colored">How to make prompt colored?</a></li>
88
+ <li><a href="#how-to-disable-command-echoback">How to disable command echoback?</a></li>
89
+ </ul></li>
90
+ <li><a href="#license-and-copyright">License and Copyright</a></li>
91
+ </ul>
92
+ </div>
93
+ </section>
94
+ </section>
95
+ <section class="section" id="install">
96
+ <h2>Install</h2>
97
+ <pre>
98
+ $ gem install benry-unixcommand
99
+ </pre>
100
+ <p>File: ex1.rb</p>
101
+ <pre class="language-ruby">
102
+ <strong>require 'benry/unixcommand'</strong> # !!!!!
103
+ <strong>include Benry::UnixCommand</strong> # !!!!!
104
+
105
+ output = <strong>capture2</strong> "uname -srmp" # run command and return output
106
+ p output
107
+ </pre>
108
+ <p>Result:</p>
109
+ <pre class="language-terminal">
110
+ [localhost]$ ruby ex1.rb
111
+ $ uname -srmp
112
+ "Darwin 22.5.0 arm64 arm\n"
113
+ </pre>
114
+ </section>
115
+ <section class="section" id="command-reference">
116
+ <h2>Command Reference</h2>
117
+ <section class="subsection" id="echo">
118
+ <h3><code>echo</code></h3>
119
+ <p>File: ex-echo1.rb</p>
120
+ <pre class="language-ruby">
121
+ require 'benry/unixcommand'
122
+ include Benry::UnixCommand
123
+
124
+ <strong>echo</strong> "aa", "bb", "cc"
125
+
126
+ <strong>echo :n</strong>, "aa" # not print "\n"
127
+ <strong>echo</strong> "bb"
128
+ </pre>
129
+ <p>Result:</p>
130
+ <pre class="language-terminal">
131
+ [localhost]$ ruby ex_echo1.rb
132
+ $ echo aa bb cc
133
+ aa bb cc
134
+ $ echo -n aa
135
+ aa$ echo bb
136
+ bb
137
+ </pre>
138
+ <p>Options:</p>
139
+ <ul>
140
+ <li><code>echo :n</code> -- don't print "\n".</li>
141
+ </ul>
142
+ </section>
143
+ <section class="subsection" id="echoback">
144
+ <h3><code>echoback</code></h3>
145
+ <ul>
146
+ <li><code>echoback "command"</code> prints <code>$ command</code> string into stdout.</li>
147
+ <li><code>echoback "command"</code> indents command if in block of <code>cd</code> or <code>pushd</code>.</li>
148
+ </ul>
149
+ <p>File: ex-echoback1.rb</p>
150
+ <pre>
151
+ require 'benry/unixcommand'
152
+ include Benry::UnixCommand
153
+
154
+ <strong>echoback</strong> "command 123"
155
+ cd "dir1" do
156
+ <strong>echoback</strong> "command 456"
157
+ cd "dir2" do
158
+ <strong>echoback</strong> "command 789"
159
+ end
160
+ end
161
+ </pre>
162
+ <p>Result:</p>
163
+ <pre class="language-terminal">
164
+ [localhost]$ ruby ex_echoback1.rb
165
+ $ command 123
166
+ $ cd dir1
167
+ $ command 456
168
+ $ cd dir2
169
+ $ command 789
170
+ $ cd -
171
+ $ cd -
172
+ </pre>
173
+ </section>
174
+ <section class="subsection" id="cp">
175
+ <h3><code>cp</code></h3>
176
+ <ul>
177
+ <li><code>cp "x", "y"</code> copies <code>x</code> to new file <code>y'. Fails when </code>y`` already exists.</li>
178
+ <li><code>cp! "x", "y"</code> is similar to above, but overwrites <code>y</code> even if it exists.</li>
179
+ <li><code>cp "x", "y", to: "dir"</code> copies <code>x</code> and <code>y</code> into <code>dir</code>.</li>
180
+ <li><code>cp "x", "y", "dir"</code> will be error! (use <code>to: "dir"</code> instead.)</li>
181
+ <li>Glob pattern such as <code>*</code>, <code>**</code>, <code>?</code>, and <code>{}</code> are available.</li>
182
+ <li>(See <a href="#faq">FAQ</a> about <code>to:</code> keyword option.)</li>
183
+ <li>If you want to copy files with keeping directory structure, use <code>store</code> instead of <code>cp</code>.</li>
184
+ </ul>
185
+ <pre class="language-ruby">
186
+ require 'benry/unixcommand'
187
+ include Benry::UnixCommand
188
+
189
+ ## copy file to newfile
190
+ <strong>cp</strong> "file1.txt", "newfile.txt" # error if newfile.txt already exists.
191
+ <strong>cp!</strong> "file1.txt", "newfile.txt" # overrides newfile.txt if exists.
192
+
193
+ ## copy dir to newdir recursively
194
+ <strong>cp :r</strong>, "dir1", "newdir" # error if newdir already exists.
195
+
196
+ ## copy files to existing directory
197
+ <strong>cp :pr</strong>, "file*.txt", "lib/**/*.rb", <strong>to:</strong> "dir1" # error if dir1 not exist.
198
+ </pre>
199
+ <p>Options:</p>
200
+ <ul>
201
+ <li><code>cp :p</code> -- preserves timestamps and permission.</li>
202
+ <li><code>cp :r</code> -- copies files and directories recursively.</li>
203
+ <li><code>cp :l</code> -- creates hard links instead of copying files.</li>
204
+ <li><code>cp :f</code> -- ignores non-existing source files.
205
+ Notice that this is different from <code>cp -f</code> of unix command.</li>
206
+ </ul>
207
+ </section>
208
+ <section class="subsection" id="mv">
209
+ <h3><code>mv</code></h3>
210
+ <ul>
211
+ <li><code>mv "x", "y"</code> renames <code>x</code> to <code>y</code>. Fails when <code>y</code> already exists.</li>
212
+ <li><code>mv! "x", "y"</code> is similar to above, but overwrites <code>y</code> even if it exists.</li>
213
+ <li><code>mv "x", "y", to: "dir"</code> moves <code>x</code> and <code>y</code> into <code>dir</code>.</li>
214
+ <li><code>mv "x", "y", "dir"</code> will be error! (use <code>to: "dir"</code> instead.)</li>
215
+ <li>Glob patten such as <code>*</code>, <code>**</code>, <code>?</code>, and <code>{}</code> are available.</li>
216
+ <li>(See <a href="#faq">FAQ</a> about <code>to:</code> keyword option.)</li>
217
+ </ul>
218
+ <pre class="language-ruby">
219
+ require 'benry/unixcommand'
220
+ include Benry::UnixCommand
221
+
222
+ ## rename file
223
+ <strong>mv</strong> "file1.txt", "newfile.txt" # error if newfile.txt already exists.
224
+ <strong>mv!</strong> "file1.txt", "newfile.txt" # overrides newfile.txt if exists.
225
+
226
+ ## rename directory
227
+ <strong>mv</strong> "dir1", "newdir" # error if newdir already exists.
228
+
229
+ ## move files and directories to existing directory
230
+ <strong>mv</strong> "file*.txt", "lib", <strong>to:</strong> "dir1" # error if dir1 not exist.
231
+
232
+ ## ignore non-existing files.
233
+ <strong>mv</strong> "foo*.txt", <strong>to:</strong> "dir1" # error if foo*.txt not exist.
234
+ <strong>mv :f</strong>, "foo*.txt", <strong>to:</strong> "dir1" # not error even if foo*.txt not exist.
235
+ </pre>
236
+ <p>Options:</p>
237
+ <ul>
238
+ <li><code>mv :f</code> -- ignores non-existing source files.</li>
239
+ </ul>
240
+ </section>
241
+ <section class="subsection" id="rm">
242
+ <h3><code>rm</code></h3>
243
+ <ul>
244
+ <li><code>rm "x", "y"</code> removes file <code>x</code> and <code>y</code>.</li>
245
+ <li><code>rm :r, "dir1"</code> removes directory recursively.</li>
246
+ <li><code>rm "dir1"</code> will raise error because <code>:r</code> option not specified.</li>
247
+ <li><code>rm "foo*.txt"</code> will raise error if <code>foo*.txt</code> not exists.</li>
248
+ <li><code>rm :f, "foo*.txt"</code> will not raise error even if <code>foo*.txt</code> not exists.</li>
249
+ <li>Glob patten such as <code>*</code>, <code>**</code>, <code>?</code>, and <code>{}</code> are available.</li>
250
+ </ul>
251
+ <pre class="language-ruby">
252
+ require 'benry/unixcommand'
253
+ include Benry::UnixCommand
254
+
255
+ ## remove files
256
+ <strong>rm</strong> "foo*.txt", "bar*.txt" # error if files not exist.
257
+ <strong>rm :f</strong>, "foo*.txt", "bar*.txt" # not error even if files not exist.
258
+
259
+ ## remove directory
260
+ <strong>rm :r</strong>, "dir1" # error if dir1 not exist.
261
+ <strong>rm :rf</strong>, "dir1" # not error even if dir1 not exist.
262
+ </pre>
263
+ <p>Options:</p>
264
+ <ul>
265
+ <li><code>rm :r</code> -- remove files and directories recursively.</li>
266
+ <li><code>rm :f</code> -- ignores non-existing files and directories.</li>
267
+ </ul>
268
+ </section>
269
+ <section class="subsection" id="mkdir">
270
+ <h3><code>mkdir</code></h3>
271
+ <ul>
272
+ <li><code>mkdir "x", "y"</code> creates <code>x</code> and <code>y</code> directories.</li>
273
+ <li><code>mkdir :p, "x/y/z"</code> creates <code>x/y/z</code> directory.</li>
274
+ <li><code>mkdir "x"</code> will be error if <code>x</code> already exists.</li>
275
+ <li><code>mkdir :p, "x"</code> will not be error even if <code>x</code> already exists.</li>
276
+ <li><code>mkdir :m, 0775, "x"</code> creates new directory with permission 0775.</li>
277
+ </ul>
278
+ <pre class="language-ruby">
279
+ require 'benry/unixcommand'
280
+ include Benry::UnixCommand
281
+
282
+ ## creates new directory
283
+ <strong>mkdir</strong> "newdir"
284
+
285
+ ## creates new directory with path
286
+ <strong>mkdir :p</strong>, "dir/x/y/z"
287
+
288
+ ## creats new directory with specific permission
289
+ <strong>mkdir :m, 0755</strong>, "newdir"
290
+ </pre>
291
+ <p>Options:</p>
292
+ <ul>
293
+ <li><code>mkdir :p</code> -- creates intermediate path.</li>
294
+ <li><code>mkdir :m, 0XXX</code> -- specifies directory permission.</li>
295
+ </ul>
296
+ </section>
297
+ <section class="subsection" id="rmdir">
298
+ <h3><code>rmdir</code></h3>
299
+ <ul>
300
+ <li><code>rmdir "x", "y"</code> removed empty directores.</li>
301
+ <li>Raises error when directory not empty.</li>
302
+ </ul>
303
+ <pre class="language-ruby">
304
+ require 'benry/unixcommand'
305
+ include Benry::UnixCommand
306
+
307
+ ## remove empty directory
308
+ <strong>rmdir</strong> "dir" # error if directory not empty.
309
+ </pre>
310
+ <p>Options:</p>
311
+ <ul>
312
+ <li>(no options)</li>
313
+ </ul>
314
+ </section>
315
+ <section class="subsection" id="ln">
316
+ <h3><code>ln</code></h3>
317
+ <ul>
318
+ <li><code>ln "x", "y"</code> creates hard link.</li>
319
+ <li><code>ln :s, "x", "y"</code> creates symbolic link. Error if <code>y</code> already exists.</li>
320
+ <li><code>ln! :s, "x", "y"</code> overwrites existing symbolic link <code>y</code>.</li>
321
+ <li><code>ln "files*.txt', to: "dir"</code> creates hard links into <code>dir</code>.</li>
322
+ <li><code>ln "files*.txt', "dir"</code> will be error! (use <code>to: "dir"</code> instead.)</li>
323
+ <li>(See <a href="#faq">FAQ</a> about <code>to:</code> keyword option.)</li>
324
+ </ul>
325
+ <pre class="language-ruby">
326
+ require 'benry/unixcommand'
327
+ include Benry::UnixCommand
328
+
329
+ ## create hard link
330
+ <strong>ln</strong> "foo1.txt", "dir/foo1.txt"
331
+
332
+ ## create symbolic link
333
+ <strong>ln :s</strong>, "foo1.txt", "dir/foo1.txt" # error if dir/foo1.txt alreay exists.
334
+ <strong>ln! :s</strong>, "foo1.txt", "dir/foo1.txt" # overwrites dir/foo1.txt if exists.
335
+
336
+ ## create symbolic link into directory.
337
+ <strong>ln :s</strong>, "foo1.txt", <strong>to:</strong> "dir"
338
+
339
+ ## error! use ``to: "dir"`` instead.
340
+ <strong>ln :s</strong>, "foo1.txt", "dir"
341
+ </pre>
342
+ </section>
343
+ <section class="subsection" id="atomic_symlink">
344
+ <h3><code>atomic_symlink!</code></h3>
345
+ <ul>
346
+ <li><code>atomic_symlink! "x", "y"</code> creates symbolic link atomically.</li>
347
+ </ul>
348
+ <pre class="language-ruby">
349
+ require 'benry/unixcommand'
350
+ include Benry::UnixCommand
351
+
352
+ ## create symbolic link atomically
353
+ <strong>atomic_symlink!</strong> "src-20200101", "src"
354
+
355
+ ## the above is same as the following
356
+ tmplink = "src.#{rand().to_s[2..6]}" # random name
357
+ File.symlink("src-20200101", tmplink) # create symblink with random name
358
+ File.rename(tmplink, "src") # rename symlink atomically
359
+ </pre>
360
+ <p>Options:</p>
361
+ <ul>
362
+ <li>(no options)</li>
363
+ </ul>
364
+ </section>
365
+ <section class="subsection" id="touch">
366
+ <h3><code>touch</code></h3>
367
+ <ul>
368
+ <li><code>touch "x"</code> updates timestamp of file.</li>
369
+ <li><code>touch :r, "reffile", "x"</code> uses timestamp of <code>reffile</code> instead current timestamp.</li>
370
+ </ul>
371
+ <pre class="language-ruby">
372
+ require 'benry/unixcommand'
373
+ include Benry::UnixCommand
374
+
375
+ ## updates timestamp of files to current timestamp.
376
+ <strong>touch</strong> "files*.txt"
377
+
378
+ ## copy timestamp from reffile to other files.
379
+ <strong>touch :r, "reffile"</strong>, "files*.txt"
380
+ </pre>
381
+ <p>Options:</p>
382
+ <ul>
383
+ <li><code>touch :a</code> -- updates only access time.</li>
384
+ <li><code>touch :m</code> -- updates only modification time.</li>
385
+ <li><code>touch :r, "reffile"</code> -- uses timestamp of <code>reffile</code> instead of current timestamp.</li>
386
+ </ul>
387
+ </section>
388
+ <section class="subsection" id="chmod">
389
+ <h3><code>chmod</code></h3>
390
+ <ul>
391
+ <li><code>chmod 0644, "x"</code> changes file permission.</li>
392
+ <li><code>chmod :R, "a+r", "dir"</code> changes permissions recursively.</li>
393
+ <li>Permission can be <code>0644</code> sytle, or <code>u+w</code> style.</li>
394
+ </ul>
395
+ <pre class="language-ruby">
396
+ require 'benry/unixcommand'
397
+ include Benry::UnixCommand
398
+
399
+ ## change permissions of files.
400
+ <strong>chmod 0644</strong>, "file*.txt"
401
+ <strong>chmod "a+r"</strong>, "file*.txt"
402
+
403
+ ## change permissions recursively.
404
+ <strong>chmod :R, 0644</strong>, "dir"
405
+ <strong>chmod :R, "a+r"</strong>, "dir"
406
+ </pre>
407
+ <p>Options:</p>
408
+ <ul>
409
+ <li><code>chmod :R</code> -- changes permissions recursively.</li>
410
+ </ul>
411
+ </section>
412
+ <section class="subsection" id="chown">
413
+ <h3><code>chown</code></h3>
414
+ <ul>
415
+ <li><code>chown "user:group", "x", "y"</code> changes owner and group of files.</li>
416
+ <li><code>chown "user", "x", "y"</code> changes owner of files.</li>
417
+ <li><code>chown ":group", "x", "y"</code> changes group of files.</li>
418
+ <li><code>chown :R, "user:group", "dir"</code> changes owner and group recursively.</li>
419
+ </ul>
420
+ <pre class="language-ruby">
421
+ require 'benry/unixcommand'
422
+ include Benry::UnixCommand
423
+
424
+ ## change owner and/or group.
425
+ <strong>chown "user1:group1"</strong>, "file*.txt" # change both owner and group
426
+ <strong>chown "user1"</strong>, "file*.txt" # change owner
427
+ <strong>chown ":group1"</strong>, "file*.txt" # change group
428
+ </pre>
429
+ <p>Options:</p>
430
+ <ul>
431
+ <li><code>chown :R</code> -- changes owner and/or group recursively.</li>
432
+ </ul>
433
+ </section>
434
+ <section class="subsection" id="pwd">
435
+ <h3><code>pwd</code></h3>
436
+ <ul>
437
+ <li><code>pwd()</code> prints current working directory path.</li>
438
+ </ul>
439
+ <pre class="language-ruby">
440
+ require 'benry/unixcommand'
441
+ include Benry::UnixCommand
442
+
443
+ ## prints current working directory
444
+ <strong>pwd()</strong> #=&gt; /home/yourname (for example)
445
+ </pre>
446
+ <p>Options:</p>
447
+ <ul>
448
+ <li>(no options)</li>
449
+ </ul>
450
+ </section>
451
+ <section class="subsection" id="cd">
452
+ <h3><code>cd</code></h3>
453
+ <ul>
454
+ <li><code>cd</code> changes current working directory.</li>
455
+ <li>If block given, <code>cd</code> invokes block just after changing current directory,
456
+ and back to previous directory automatically.</li>
457
+ <li>Within block argument, echoback indentation is increased.</li>
458
+ <li><code>chdir</code> is an alias to <code>cd</code>.</li>
459
+ </ul>
460
+ <p>File: ex-cd1.rb</p>
461
+ <pre class="language-ruby">
462
+ require 'benry/unixcommand'
463
+ include Benry::UnixCommand
464
+
465
+ ## change directory, invoke block, and back to previous directory.
466
+ pwd() #=&gt; /home/yourname (for example)
467
+ <strong>cd</strong> "/tmp" <strong>do</strong>
468
+ pwd() #=&gt; /tmp
469
+ end
470
+ pwd() #=&gt; /home/yourname (for example)
471
+
472
+ ## just change directory
473
+ <strong>cd</strong> "/tmp"
474
+ pwd() #=&gt; /tmp
475
+ </pre>
476
+ <p>Result:</p>
477
+ <pre class="language-terminal">
478
+ [localhost]$ ruby ex-cd1.rb
479
+ $ pwd
480
+ /home/yourname
481
+ $ cd /tmp
482
+ $ pwd
483
+ /tmp
484
+ $ cd -
485
+ $ pwd
486
+ /home/yourname
487
+ $ cd /tmp
488
+ $ pwd
489
+ /tmp
490
+ </pre>
491
+ <p>Options:</p>
492
+ <ul>
493
+ <li>(no options)</li>
494
+ </ul>
495
+ </section>
496
+ <section class="subsection" id="pushd">
497
+ <h3><code>pushd</code></h3>
498
+ <ul>
499
+ <li><code>pushd</code> changes current directory, invokes block, and back to previous directory.</li>
500
+ <li><code>pushd</code> requires block argument. <code>cd</code> also takes block argument but it is an optional.</li>
501
+ <li>Within block argument, echoback indentation is increased.</li>
502
+ </ul>
503
+ <p>File: ex-pushd1.rb</p>
504
+ <pre class="language-ruby">
505
+ require 'benry/unixcommand'
506
+ include Benry::UnixCommand
507
+
508
+ ## change directory, invoke block, and back to previous directory.
509
+ pwd() #=&gt; /home/yourname (for example)
510
+ <strong>pushd</strong> "/var" <strong>do</strong>
511
+ pwd() #=&gt; /var
512
+ <strong>pushd</strong> "tmp" <strong>do</strong>
513
+ pwd() #=&gt; /var/tmp
514
+ end
515
+ pwd() #=&gt; /var
516
+ end
517
+ pwd() #=&gt; /home/yourname (for example)
518
+ </pre>
519
+ <p>Result:</p>
520
+ <pre class="language-terminal">
521
+ [localhost]$ ruby ex-pushd1.rb
522
+ $ pwd
523
+ /home/yourname
524
+ $ pushd /var
525
+ $ pwd
526
+ /var
527
+ $ pushd tmp
528
+ $ pwd
529
+ /var/tmp
530
+ $ popd # back to /var
531
+ $ pwd
532
+ /var
533
+ $ popd # back to /home/yourname
534
+ $ pwd
535
+ /home/yourname
536
+ </pre>
537
+ <p>Options:</p>
538
+ <ul>
539
+ <li>(no options)</li>
540
+ </ul>
541
+ </section>
542
+ <section class="subsection" id="store">
543
+ <h3><code>store</code></h3>
544
+ <ul>
545
+ <li><code>store "x", "y", to: "dir", </code> copies files under <code>x</code> and <code>y</code> to <code>dir</code> keeping file path.
546
+ For example, <code>x/foo/bar.rb</code> will be copied as <code>dir/x/foo/bar.rb</code>.</li>
547
+ <li><code>store!</code> overwrites existing files while <code>store</code> doesn't.</li>
548
+ </ul>
549
+ <pre class="language-ruby">
550
+ require 'benry/unixcommand'
551
+ include Benry::UnixCommand
552
+
553
+ ## copies files into builddir, keeping file path
554
+ <strong>store</strong> "lib/**/*.rb", "test/**/*.rb", <strong>to:</strong> "builddir"
555
+
556
+ ## `store()` is similar to unix `tar` command.
557
+ ## $ tar cf - lib/**/*.rb test/**/*.rb | (cd builddir; tar xf -)
558
+ </pre>
559
+ <p>Options:</p>
560
+ <ul>
561
+ <li><code>store :p</code> -- preserves timestamps, permission, file owner and group.</li>
562
+ <li><code>store :l</code> -- creates hard link instead of copying file.</li>
563
+ <li><code>store :f</code> -- ignores non-existing files.</li>
564
+ </ul>
565
+ </section>
566
+ <section class="subsection" id="sys">
567
+ <h3><code>sys</code></h3>
568
+ <ul>
569
+ <li><code>sys "ls -al"</code> runs <code>ls -al</code> command.</li>
570
+ <li><code>sys</code> raises error when command failed.</li>
571
+ <li><code>sys!</code> ignores error even when command failed.</li>
572
+ <li><code>sys</code> and <code>sys!</code> return <code>Process::Status</code> object regardless of command result.</li>
573
+ <li><code>sys</code> and <code>sys!</code> can take a block argument as error handler called only when command failed.
574
+ If result of block argument is truthy, error will not be raised.</li>
575
+ </ul>
576
+ <pre class="language-ruby">
577
+ require 'benry/unixcommand'
578
+ include Benry::UnixCommand
579
+
580
+ ## run ``ls`` command
581
+ <strong>sys</strong> "ls foo.txt" # may raise error when command failed
582
+ <strong>sys!</strong> "ls foo.txt" # ignore error even when command filed
583
+
584
+ ## error handling
585
+ <strong>sys</strong> "ls /fooobarr" <strong>do</strong> |stat| # block called only when command failed
586
+ p stats.class #=&gt; Process::Status
587
+ p stat.exitstatus #=&gt; 1 (non-zero)
588
+ true # suppress raising error
589
+ end
590
+ </pre>
591
+ <ul>
592
+ <li><code>sys "echo *.txt"</code> (a single string) invokes <code>echo</code> command via shell.</li>
593
+ <li><code>sys "echo", "*.txt"</code> (multiple strings) invokes <code>echo</code> command without shell,
594
+ and <code>*.txt</code> will be globbed by <code>sys</code>.</li>
595
+ <li><code>sys ["echo", "*.txt"]</code> (an array of strings) invokes <code>echo</code> command without shell,
596
+ and <code>*.txt</code> will NOT be globbed by <code>sys</code>.
597
+ If you need to run command without shell nor globbing, <code>sys ["command ..."]</code> is the solution.</li>
598
+ <li><code>sys ["echo"], "*.txt"</code> raises error.</li>
599
+ </ul>
600
+ <pre class="language-ruby">
601
+ require 'benry/unixcommand'
602
+ include Benry::UnixCommand
603
+
604
+ ## Example: assume that there are two files "A.txt" and "B.txt".
605
+
606
+ ## with shell, with globbing (by shell) ### Output:
607
+ sys <strong>"echo *.txt"</strong> # $ echo <strong>*.txt</strong>
608
+ # A.txt B.txt
609
+
610
+ ## no shell, with globbing (by `sys`) ### Output:
611
+ sys <strong>"echo", "*.txt"</strong> # $ echo <strong>*.txt</strong>
612
+ # A.txt B.txt
613
+
614
+ ## no shell, no globbing ### Output:
615
+ sys <strong>["echo", "*.txt"]</strong> # $ echo <strong>*.txt</strong>
616
+ # <strong>*.txt</strong>
617
+
618
+ ## error
619
+ sys <strong>["echo"], "*.txt"</strong> #=&gt; ArgumentError
620
+ </pre>
621
+ <p>Options:</p>
622
+ <ul>
623
+ <li><code>sys :q</code> -- quiet mode (suppress echoback of command).</li>
624
+ </ul>
625
+ </section>
626
+ <section class="subsection" id="ruby">
627
+ <h3><code>ruby</code></h3>
628
+ <ul>
629
+ <li><code>ruby "...."</code> is almost same as <code>sys "ruby ...."</code>.</li>
630
+ <li><code>RbConfig.ruby</code> is used as ruby command path.</li>
631
+ <li><code>ruby</code> raises error when ruby command failed.</li>
632
+ <li><code>ruby!</code> ignores error even when ruby command failed.</li>
633
+ </ul>
634
+ <pre class="language-ruby">
635
+ require 'benry/unixcommand'
636
+ include Benry::UnixCommand
637
+
638
+ ## run ruby command
639
+ <strong>ruby</strong> "file1.rb" # raise error when ruby command failed
640
+ <strong>ruby!</strong> "file1.rb" # ignore error even when ruby command filed
641
+ </pre>
642
+ <p>Options:</p>
643
+ <ul>
644
+ <li>(no options)</li>
645
+ </ul>
646
+ </section>
647
+ <section class="subsection" id="capture2">
648
+ <h3><code>capture2</code></h3>
649
+ <ul>
650
+ <li><code>capture2 "ls -al"</code> runs <code>ls -al</code> and returns output of the command.</li>
651
+ <li><code>capture2 "cat -n", stdin_data: "A\nB\n"</code> run <code>cat -n</code> command and uses <code>"A\nB\n"</code> as stdin data.</li>
652
+ <li><code>caputre2 "ls foo"</code> will raise error when command failed.</li>
653
+ <li><code>caputre2! "ls foo"</code> ignores error even when command failed, and returns command output and process status object.</li>
654
+ <li><code>capture2()</code> invokes <code>Popen3.capture2()</code> internally. All keyword arguments are available.</li>
655
+ </ul>
656
+ <pre class="language-ruby">
657
+ require 'benry/unixcommand'
658
+ include Benry::UnixCommand
659
+
660
+ ## run command and get output of the command.
661
+ output = <strong>capture2</strong> "ls -l foo.txt" # error if command failed
662
+ output, process_status = <strong>capture2!</strong> "ls -l foot.xt" # ignore error even command failed
663
+ puts process_status.exitstatus #=&gt; 1
664
+
665
+ ## run command with stdin data.
666
+ input = "AA\nBB\nCC\n"
667
+ output = <strong>capture2</strong> "cat -n", <strong>stdin_data: input</strong>
668
+ </pre>
669
+ <p>Options:</p>
670
+ <ul>
671
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture2">``Popen3.capture2()`` manual page</a>.</li>
672
+ </ul>
673
+ </section>
674
+ <section class="subsection" id="capture2e">
675
+ <h3><code>capture2e</code></h3>
676
+ <ul>
677
+ <li>almost same as <code>capture2</code>, but output contains both stdout and stderr.</li>
678
+ </ul>
679
+ <pre class="language-ruby">
680
+ require 'benry/unixcommand'
681
+ include Benry::UnixCommand
682
+
683
+ ## run command and get output of the command, including stderr.
684
+ output = <strong>capture2e</strong> "time ls -al"
685
+ output, process_status = <strong>capture2e!</strong> "time ls -al" # ignore error even command failed
686
+ puts process_status.exitstatus
687
+ </pre>
688
+ <p>Options:</p>
689
+ <ul>
690
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture2e">``Popen3.capture2e()`` manual page</a>.</li>
691
+ </ul>
692
+ </section>
693
+ <section class="subsection" id="capture3">
694
+ <h3><code>capture3</code></h3>
695
+ <ul>
696
+ <li>almost same as <code>capture2</code>, but returns both stdout output and stderr output.</li>
697
+ </ul>
698
+ <pre class="language-ruby">
699
+ require 'benry/unixcommand'
700
+ include Benry::UnixCommand
701
+
702
+ ## run command and get output of both stdout and stderr separately
703
+ output, error = <strong>capture3</strong> "time ls -al"
704
+ output, error, process_status = <strong>capture3!</strong> "time ls -al" # ignore error even command failed
705
+ puts process_status.exitstatus
706
+
707
+ ## run command with stdin data.
708
+ input = "AA\nBB\nCC\n"
709
+ output, error = <strong>capture3</strong> "cat -n", <strong>stdin_data: input</strong>
710
+ </pre>
711
+ <p>Options:</p>
712
+ <ul>
713
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture3">``Popen3.capture3()`` manual page</a>.</li>
714
+ </ul>
715
+ </section>
716
+ <section class="subsection" id="zip">
717
+ <h3><code>zip</code></h3>
718
+ <ul>
719
+ <li><code>zip "foo.zip", "file1", "file2"</code> creates new zip file <code>foo.zip</code>.</li>
720
+ <li><code>zip :r, "foo.zip", "dir1"</code> adds files under <code>dir1</code> into zip file recursively.</li>
721
+ <li><code>zip</code> will be error if zip file already exists.</li>
722
+ <li><code>zip!</code> will overwrite existing zip file.</li>
723
+ <li><code>zip :'0'</code> doesn't compress files.</li>
724
+ <li><code>zip :'1'</code> compress files in best speed.</li>
725
+ <li><code>zip :'9'</code> compress files in best compression level.</li>
726
+ <li><code>zip</code> and <code>zip!</code> loads <code>rubyzip</code> gem automatically. You must install it by yourself.</li>
727
+ <li>(<code>rubyzip</code> gem is necessary ONLY when <code>zip</code> or <code>zip!</code> command is invoked.)</li>
728
+ <li><code>zip</code> and <code>zip!</code> doesn't support absolute path.</li>
729
+ </ul>
730
+ <pre class="language-ruby">
731
+ require 'benry/unixcommand'
732
+ include Benry::UnixCommand
733
+
734
+ ## create zip file
735
+ <strong>zip</strong> "foo.zip", "file*.txt" # requires 'rubyzip' gem
736
+
737
+ ## create zip file, adding files under directory
738
+ <strong>zip :r</strong>, "foo.zip", "dir1"
739
+
740
+ ## create high-compressed zip file
741
+ <strong>zip :r9</strong>, "foo.zip", "dir1"
742
+ </pre>
743
+ <p>Options:</p>
744
+ <ul>
745
+ <li><code>zip :r</code> -- adds files under directory into zip file recursively.</li>
746
+ <li><code>zip :'0'</code> -- not compress files.</li>
747
+ <li><code>zip :'1'</code> -- compress files in best speed.</li>
748
+ <li><code>zip :'9'</code> -- compress files in best compression level.</li>
749
+ </ul>
750
+ </section>
751
+ <section class="subsection" id="unzip">
752
+ <h3><code>unzip</code></h3>
753
+ <ul>
754
+ <li><code>unzip "foo.zip"</code> extracts files in zip file into current directory.</li>
755
+ <li><code>unzip :d, "dir1", "foo.zip"</code> extracts files under <code>dir1</code>.
756
+ Diretory <code>dir1</code> should not exist or should be empty.</li>
757
+ <li><code>unzip "foo.zip"</code> will be error if extracting file already exists.</li>
758
+ <li><code>unzip! "foo.zip"</code> will overwrite existing files.</li>
759
+ <li><code>unzip "foo.txt", "file1", "file2"</code> extracts only <code>file1</code> and <code>file2</code>.</li>
760
+ <li><code>zunip</code> and <code>unzip!</code> loads <code>rubyzip</code> gem automatically. You must install it by yourself.</li>
761
+ <li>(<code>rubyzip</code> gem is necessary ONLY when <code>unzip</code> or <code>unzip!</code> command is invoked.)</li>
762
+ <li><code>unzip</code> and <code>unzip!</code> doesn't support absolute path.</li>
763
+ </ul>
764
+ <pre class="language-ruby">
765
+ require 'benry/unixcommand'
766
+ include Benry::UnixCommand
767
+
768
+ ## extracts zip file
769
+ <strong>unzip</strong> "foo.zip" # requires 'rubyzip' gem
770
+
771
+ ## extracts files in zip file into the directory.
772
+ <strong>unzip :d</strong>, "dir1", "foo.zip" # 'dir1' should be empty, or should not exist
773
+
774
+ ## overwrites existing files.
775
+ <strong>unzip!</strong> "foo.zip"
776
+ </pre>
777
+ <p>Options:</p>
778
+ <ul>
779
+ <li><code>unzip :d, "dir1"</code> -- extracts files into the directory.</li>
780
+ </ul>
781
+ </section>
782
+ <section class="subsection" id="time">
783
+ <h3><code>time</code></h3>
784
+ <ul>
785
+ <li><code>time do ... end</code> invokes block and prints elapsed time into stderr.</li>
786
+ </ul>
787
+ <p>File: ex-time1.rb</p>
788
+ <pre class="language-ruby">
789
+ require 'benry/unixcommand'
790
+ include Benry::UnixCommand
791
+
792
+ <strong>time do</strong>
793
+ sys "zip -qr9 dir1.zip dir1"
794
+ end
795
+ </pre>
796
+ <p>Result:</p>
797
+ <pre class="language-termianl">
798
+ [localhost]$ ruby ex-time1.rb
799
+ $ zip -qr9 dir1.zip dir1
800
+
801
+ 1.511s real 1.501s user 0.006s sys
802
+ </pre>
803
+ </section>
804
+ </section>
805
+ <section class="section" id="faq">
806
+ <h2>FAQ</h2>
807
+ <section class="subsection" id="why-mv-or-cp-requires-to-option">
808
+ <h3>Why <code>mv</code> or <code>cp</code> requires <code>to:</code> option?</h3>
809
+ <p>Because UNIX command has bad interface which causes unexpected result.</p>
810
+ <p>For example, <code>mv</code> command of UNIX has two function: <strong>rename</strong> and <strong>move</strong>.</p>
811
+ <ul>
812
+ <li>rename: <code>mv foo bar</code> (if <code>bar</code> is a file or not exist)</li>
813
+ <li>move: <code>mv foo bar</code> (if directory <code>bar</code> already exists)</li>
814
+ </ul>
815
+ <p>Obviously, rename function and move function are same form.
816
+ This causes unexpected result easily due to, for example, typo.</p>
817
+ <pre class="language-terminal">
818
+ ### Assume that you want rename 'foo' file to 'bar'.
819
+ ### But if 'bar' exists as directory, mv command moves 'foo' into 'bar'.
820
+ ### In this case, mv command should be error.
821
+ $ <strong>mv foo bar</strong>
822
+ </pre>
823
+ <p>To avoid this unexpected result, <code>mv()</code> command of Benry::UnixCommand handles two functions in different forms.</p>
824
+ <ul>
825
+ <li>rename: <code>mv "foo", "bar"</code> (error if directory <code>bar</code> exists)</li>
826
+ <li>move: <code>mv "foo", to: "bar"</code> (error if 'bar' is a file or not exist)</li>
827
+ </ul>
828
+ <p>In the same reason, <code>cp()</code> and <code>ln()</code> of Benry::UnixCommand also requires <code>to:</code> option.</p>
829
+ </section>
830
+ <section class="subsection" id="how-to-use-in-rakefile">
831
+ <h3>How to use in Rakefile?</h3>
832
+ <p>File: Rakefile</p>
833
+ <pre class="language-ruby">
834
+ <strong>require 'benry/unixcommand'</strong> # !!!!!
835
+ <strong>include Benry::UnixCommand</strong> # !!!!!
836
+ <strong>Rake::DSL.prepend Benry::UnixCommand</strong> # !!!!!
837
+
838
+ task :example do
839
+ ## invoke commands defined in Benry::UnixCommand, not in Rake nor fileutils.rb
840
+ <strong>mkdir :p</strong>, "foo/bar/baz"
841
+ here = Dir.pwd()
842
+ <strong>pushd</strong> "foo/bar/baz" do
843
+ output = <strong>capture2</strong> "pwd"
844
+ puts output.sub(here+"/", "")
845
+ end
846
+ end
847
+ </pre>
848
+ <p>Result:</p>
849
+ <pre class="language-terminal">
850
+ [localhost]$ <strong>rake example</strong>
851
+ $ mkdir -p foo/bar/baz
852
+ $ pushd foo/bar/baz
853
+ $ pwd
854
+ foo/bar/baz
855
+ $ popd # back to /home/yourname
856
+ </pre>
857
+ </section>
858
+ <section class="subsection" id="how-to-change-prompt-string">
859
+ <h3>How to change prompt string?</h3>
860
+ <p>File: ex-prompt1.rb</p>
861
+ <pre class="language-ruby">
862
+ require 'benry/unixcommand'
863
+ include Benry::UnixCommand
864
+
865
+ <strong>def prompt()</strong> # !!!!!
866
+ <strong>"myname@localhost&gt; "</strong> # !!!!!
867
+ <strong>end</strong> # !!!!!
868
+
869
+ sys "date"
870
+ </pre>
871
+ <p>Result:</p>
872
+ <pre class="language-terminal">
873
+ [localhost]$ ruby ex-prompt1.rb
874
+ myname@localhost&gt; date
875
+ Wed Jan 15 20:23:07 UTC 2021
876
+ </pre>
877
+ </section>
878
+ <section class="subsection" id="how-to-make-prompt-colored">
879
+ <h3>How to make prompt colored?</h3>
880
+ <pre class="language-ruby">
881
+ require 'benry/unixcommand'
882
+ include Benry::UnixCommand
883
+
884
+ def prompt()
885
+ s = "myname@localhost&gt;"
886
+ <strong>"\e[31m#{s}\e[0m "</strong> # red
887
+ #"\e[32m#{s}\e[0m " # green
888
+ #"\e[33m#{s}\e[0m " # yellow
889
+ #"\e[34m#{s}\e[0m " # blue
890
+ #"\e[35m#{s}\e[0m " # magenta
891
+ #"\e[36m#{s}\e[0m " # cyan
892
+ #"\e[37m#{s}\e[0m " # white
893
+ #"\e[1m#{s}\e[0m " # bold
894
+ #"\e[2m#{s}\e[0m " # gray
895
+ end
896
+
897
+ sys "date"
898
+ </pre>
899
+ </section>
900
+ <section class="subsection" id="how-to-disable-command-echoback">
901
+ <h3>How to disable command echoback?</h3>
902
+ <p>File: ex-quiet1.rb</p>
903
+ <pre class="language-ruby">
904
+ require 'benry/unixcommand'
905
+ include Benry::UnixCommand
906
+
907
+ ## disable temporarily
908
+ <strong>echoback_off do</strong>
909
+ sys "date"
910
+ <strong>end</strong>
911
+
912
+ ## disable globally
913
+ <strong>$BENRY_ECHOBACK = false</strong> # !!!!!
914
+ sys "date"
915
+ </pre>
916
+ <p>Result:</p>
917
+ <pre class="language-terminal">
918
+ $ ruby ex-quiet1.rb
919
+ Wed Jan 1 22:29:55 UTC 2020 # no echoback, only output
920
+ Wed Jan 1 22:29:55 UTC 2020 # no echoback, only output
921
+ </pre>
922
+ </section>
923
+ </section>
924
+ <section class="section" id="license-and-copyright">
925
+ <h2>License and Copyright</h2>
926
+ <p>$License: MIT License $</p>
927
+ <p>$Copyright: copyright(c) 2021 kwatch@gmail.com $</p>
928
+ </section>
929
+ </section>
930
+ </main>
931
+ </body>
932
+ </html>