benry-unixcommand 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>