benry-unixcmd 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,894 @@
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-unixcmd">
19
+ <h1>Benry-UnixCmd</h1>
20
+ <nav class="nav">
21
+ <ul class="nav">
22
+ </ul>
23
+ </nav>
24
+ <p>($Release: 0.9.1 $)</p>
25
+ <section class="section" id="whats-this">
26
+ <h2>What's this?</h2>
27
+ <p>Benry-UnixCmd 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-unixcmd.html">https://kwatch.github.io/benry-ruby/benry-unixcmd.html</a></li>
31
+ <li>GitHub: <a href="https://github.com/kwatch/benry-ruby/tree/main/benry-unixcmd">https://github.com/kwatch/benry-ruby/tree/main/benry-unixcmd</a></li>
32
+ <li>Changes: <a href="https://github.com/kwatch/benry-ruby/blob/main/benry-unixcmd/CHANGES.md">https://github.com/kwatch/benry-ruby/blob/main/benry-unixcmd/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-UnixCmd 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-unixcmd
99
+ </pre>
100
+ <p>File: ex1.rb</p>
101
+ <pre class="language-ruby">
102
+ <strong>require 'benry/unixcmd'</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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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/unixcmd'
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
+ <p>Options:</p>
592
+ <ul>
593
+ <li>(no options)</li>
594
+ </ul>
595
+ </section>
596
+ <section class="subsection" id="ruby">
597
+ <h3><code>ruby</code></h3>
598
+ <ul>
599
+ <li><code>ruby "...."</code> is almost same as <code>sys "ruby ...."</code>.</li>
600
+ <li><code>RbConfig.ruby</code> is used as ruby command path.</li>
601
+ <li><code>ruby</code> raises error when ruby command failed.</li>
602
+ <li><code>ruby!</code> ignores error even when ruby command failed.</li>
603
+ </ul>
604
+ <pre class="language-ruby">
605
+ require 'benry/unixcmd'
606
+ include Benry::UnixCommand
607
+
608
+ ## run ruby command
609
+ <strong>ruby</strong> "file1.rb" # raise error when ruby command failed
610
+ <strong>ruby!</strong> "file1.rb" # ignore error even when ruby command filed
611
+ </pre>
612
+ <p>Options:</p>
613
+ <ul>
614
+ <li>(no options)</li>
615
+ </ul>
616
+ </section>
617
+ <section class="subsection" id="capture2">
618
+ <h3><code>capture2</code></h3>
619
+ <ul>
620
+ <li><code>capture2 "ls -al"</code> runs <code>ls -al</code> and returns output of the command.</li>
621
+ <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>
622
+ <li><code>caputre2 "ls foo"</code> will raise error when command failed.</li>
623
+ <li><code>caputre2! "ls foo"</code> ignores error even when command failed, and returns command output and process status object.</li>
624
+ <li><code>capture2()</code> invokes <code>Popen3.capture2()</code> internally. All keyword arguments are available.</li>
625
+ </ul>
626
+ <pre class="language-ruby">
627
+ require 'benry/unixcmd'
628
+ include Benry::UnixCommand
629
+
630
+ ## run command and get output of the command.
631
+ output = <strong>capture2</strong> "ls -l foo.txt" # error if command failed
632
+ output, process_status = <strong>capture2!</strong> "ls -l foot.xt" # ignore error even command failed
633
+ puts process_status.exitstatus #=&gt; 1
634
+
635
+ ## run command with stdin data.
636
+ input = "AA\nBB\nCC\n"
637
+ output = <strong>capture2</strong> "cat -n", <strong>stdin_data: input</strong>
638
+ </pre>
639
+ <p>Options:</p>
640
+ <ul>
641
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture2">``Popen3.capture2()`` manual page</a>.</li>
642
+ </ul>
643
+ </section>
644
+ <section class="subsection" id="capture2e">
645
+ <h3><code>capture2e</code></h3>
646
+ <ul>
647
+ <li>almost same as <code>capture2</code>, but output contains both stdout and stderr.</li>
648
+ </ul>
649
+ <pre class="language-ruby">
650
+ require 'benry/unixcmd'
651
+ include Benry::UnixCommand
652
+
653
+ ## run command and get output of the command, including stderr.
654
+ output = <strong>capture2e</strong> "time ls -al"
655
+ output, process_status = <strong>capture2e!</strong> "time ls -al" # ignore error even command failed
656
+ puts process_status.exitstatus
657
+ </pre>
658
+ <p>Options:</p>
659
+ <ul>
660
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture2e">``Popen3.capture2e()`` manual page</a>.</li>
661
+ </ul>
662
+ </section>
663
+ <section class="subsection" id="capture3">
664
+ <h3><code>capture3</code></h3>
665
+ <ul>
666
+ <li>almost same as <code>capture2</code>, but returns both stdout output and stderr output.</li>
667
+ </ul>
668
+ <pre class="language-ruby">
669
+ require 'benry/unixcmd'
670
+ include Benry::UnixCommand
671
+
672
+ ## run command and get output of both stdout and stderr separately
673
+ output, error = <strong>capture3</strong> "time ls -al"
674
+ output, error, process_status = <strong>capture3!</strong> "time ls -al" # ignore error even command failed
675
+ puts process_status.exitstatus
676
+
677
+ ## run command with stdin data.
678
+ input = "AA\nBB\nCC\n"
679
+ output, error = <strong>capture3</strong> "cat -n", <strong>stdin_data: input</strong>
680
+ </pre>
681
+ <p>Options:</p>
682
+ <ul>
683
+ <li>see <a href="https://docs.ruby-lang.org/en/master/Open3.html#method-c-capture3">``Popen3.capture3()`` manual page</a>.</li>
684
+ </ul>
685
+ </section>
686
+ <section class="subsection" id="zip">
687
+ <h3><code>zip</code></h3>
688
+ <ul>
689
+ <li><code>zip "foo.zip", "file1", "file2"</code> creates new zip file <code>foo.zip</code>.</li>
690
+ <li><code>zip :r, "foo.zip", "dir1"</code> adds files under <code>dir1</code> into zip file recursively.</li>
691
+ <li><code>zip</code> will be error if zip file already exists.</li>
692
+ <li><code>zip!</code> will overwrite existing zip file.</li>
693
+ <li><code>zip :'0'</code> doesn't compress files.</li>
694
+ <li><code>zip :'1'</code> compress files in best speed.</li>
695
+ <li><code>zip :'9'</code> compress files in best compression level.</li>
696
+ <li><code>zip</code> and <code>zip!</code> loads <code>rubyzip</code> gem automatically. You must install it by yourself.</li>
697
+ <li>(<code>rubyzip</code> gem is necessary ONLY when <code>zip</code> or <code>zip!</code> command is invoked.)</li>
698
+ <li><code>zip</code> and <code>zip!</code> doesn't support absolute path.</li>
699
+ </ul>
700
+ <pre class="language-ruby">
701
+ require 'benry/unixcmd'
702
+ include Benry::UnixCommand
703
+
704
+ ## create zip file
705
+ <strong>zip</strong> "foo.zip", "file*.txt" # requires 'rubyzip' gem
706
+
707
+ ## create zip file, adding files under directory
708
+ <strong>zip :r</strong>, "foo.zip", "dir1"
709
+
710
+ ## create high-compressed zip file
711
+ <strong>zip :r9</strong>, "foo.zip", "dir1"
712
+ </pre>
713
+ <p>Options:</p>
714
+ <ul>
715
+ <li><code>zip :r</code> -- adds files under directory into zip file recursively.</li>
716
+ <li><code>zip :'0'</code> -- not compress files.</li>
717
+ <li><code>zip :'1'</code> -- compress files in best speed.</li>
718
+ <li><code>zip :'9'</code> -- compress files in best compression level.</li>
719
+ </ul>
720
+ </section>
721
+ <section class="subsection" id="unzip">
722
+ <h3><code>unzip</code></h3>
723
+ <ul>
724
+ <li><code>unzip "foo.zip"</code> extracts files in zip file into current directory.</li>
725
+ <li><code>unzip :d, "dir1", "foo.zip"</code> extracts files under <code>dir1</code>.
726
+ Diretory <code>dir1</code> should not exist or should be empty.</li>
727
+ <li><code>unzip "foo.zip"</code> will be error if extracting file already exists.</li>
728
+ <li><code>unzip! "foo.zip"</code> will overwrite existing files.</li>
729
+ <li><code>unzip "foo.txt", "file1", "file2"</code> extracts only <code>file1</code> and <code>file2</code>.</li>
730
+ <li><code>zunip</code> and <code>unzip!</code> loads <code>rubyzip</code> gem automatically. You must install it by yourself.</li>
731
+ <li>(<code>rubyzip</code> gem is necessary ONLY when <code>unzip</code> or <code>unzip!</code> command is invoked.)</li>
732
+ <li><code>unzip</code> and <code>unzip!</code> doesn't support absolute path.</li>
733
+ </ul>
734
+ <pre class="language-ruby">
735
+ require 'benry/unixcmd'
736
+ include Benry::UnixCommand
737
+
738
+ ## extracts zip file
739
+ <strong>unzip</strong> "foo.zip" # requires 'rubyzip' gem
740
+
741
+ ## extracts files in zip file into the directory.
742
+ <strong>unzip :d</strong>, "dir1", "foo.zip" # 'dir1' should be empty, or should not exist
743
+
744
+ ## overwrites existing files.
745
+ <strong>unzip!</strong> "foo.zip"
746
+ </pre>
747
+ <p>Options:</p>
748
+ <ul>
749
+ <li><code>unzip :d, "dir1"</code> -- extracts files into the directory.</li>
750
+ </ul>
751
+ </section>
752
+ <section class="subsection" id="time">
753
+ <h3><code>time</code></h3>
754
+ <ul>
755
+ <li><code>time do ... end</code> invokes block and prints elapsed time into stderr.</li>
756
+ </ul>
757
+ <p>File: ex-time1.rb</p>
758
+ <pre class="language-ruby">
759
+ require 'benry/unixcmd'
760
+ include Benry::UnixCommand
761
+
762
+ <strong>time do</strong>
763
+ sys "zip -qr9 dir1.zip dir1"
764
+ end
765
+ </pre>
766
+ <p>Result:</p>
767
+ <pre class="language-termianl">
768
+ [localhost]$ ruby ex-time1.rb
769
+ $ zip -qr9 dir1.zip dir1
770
+
771
+ 1.511s real 1.501s user 0.006s sys
772
+ </pre>
773
+ </section>
774
+ </section>
775
+ <section class="section" id="faq">
776
+ <h2>FAQ</h2>
777
+ <section class="subsection" id="why-mv-or-cp-requires-to-option">
778
+ <h3>Why <code>mv</code> or <code>cp</code> requires <code>to:</code> option?</h3>
779
+ <p>Because UNIX command has bad interface which causes unexpected result.</p>
780
+ <p>For example, <code>mv</code> command of UNIX has two function: <strong>rename</strong> and <strong>move</strong>.</p>
781
+ <ul>
782
+ <li>rename: <code>mv foo bar</code> (if <code>bar</code> is a file or not exist)</li>
783
+ <li>move: <code>mv foo bar</code> (if directory <code>bar</code> already exists)</li>
784
+ </ul>
785
+ <p>Obviously, rename function and move function are same form.
786
+ This causes unexpected result easily due to, for example, typo.</p>
787
+ <pre class="language-terminal">
788
+ ### Assume that you want rename 'foo' file to 'bar'.
789
+ ### But if 'bar' exists as directory, mv command moves 'foo' into 'bar'.
790
+ ### In this case, mv command should be error.
791
+ $ <strong>mv foo bar</strong>
792
+ </pre>
793
+ <p>To avoid this unexpected result, <code>mv()</code> command of Benry::UnixCommand handles two functions in different forms.</p>
794
+ <ul>
795
+ <li>rename: <code>mv "foo", "bar"</code> (error if directory <code>bar</code> exists)</li>
796
+ <li>move: <code>mv "foo", to: "bar"</code> (error if 'bar' is a file or not exist)</li>
797
+ </ul>
798
+ <p>In the same reason, <code>cp()</code> and <code>ln()</code> of Benry::UnixCommand also requires <code>to:</code> option.</p>
799
+ </section>
800
+ <section class="subsection" id="how-to-use-in-rakefile">
801
+ <h3>How to use in Rakefile?</h3>
802
+ <p>File: Rakefile</p>
803
+ <pre class="language-ruby">
804
+ <strong>require 'benry/unixcmd'</strong> # !!!!!
805
+ <strong>include Benry::UnixCommand</strong> # !!!!!
806
+ <strong>Rake::DSL.prepend Benry::UnixCommand</strong> # !!!!!
807
+
808
+ task :example do
809
+ ## invoke commands defined in Benry::UnixCommand, not in Rake nor fileutils.rb
810
+ <strong>mkdir :p</strong>, "foo/bar/baz"
811
+ here = Dir.pwd()
812
+ <strong>pushd</strong> "foo/bar/baz" do
813
+ output = <strong>capture2</strong> "pwd"
814
+ puts output.sub(here+"/", "")
815
+ end
816
+ end
817
+ </pre>
818
+ <p>Result:</p>
819
+ <pre class="language-terminal">
820
+ [localhost]$ <strong>rake example</strong>
821
+ $ mkdir -p foo/bar/baz
822
+ $ pushd foo/bar/baz
823
+ $ pwd
824
+ foo/bar/baz
825
+ $ popd # back to /home/yourname
826
+ </pre>
827
+ </section>
828
+ <section class="subsection" id="how-to-change-prompt-string">
829
+ <h3>How to change prompt string?</h3>
830
+ <p>File: ex-prompt1.rb</p>
831
+ <pre class="language-ruby">
832
+ require 'benry/unixcmd'
833
+ include Benry::UnixCommand
834
+
835
+ <strong>def prompt()</strong> # !!!!!
836
+ <strong>"myname@localhost&gt;"</strong> # !!!!!
837
+ <strong>end</strong> # !!!!!
838
+
839
+ sys "date"
840
+ </pre>
841
+ <p>Result:</p>
842
+ <pre class="language-terminal">
843
+ [localhost]$ ruby ex-prompt1.rb
844
+ myname@localhost&gt; date
845
+ Wed Jan 15 20:23:07 UTC 2021
846
+ </pre>
847
+ </section>
848
+ <section class="subsection" id="how-to-make-prompt-colored">
849
+ <h3>How to make prompt colored?</h3>
850
+ <pre class="language-ruby">
851
+ require 'benry/unixcmd'
852
+ include Benry::UnixCommand
853
+
854
+ def prompt()
855
+ s = "myname@localhost&gt;"
856
+ <strong>"\e[0;31m#{s}\e[0m"</strong> # red
857
+ #"\e[0;32m#{s}\e[0m" # green
858
+ #"\e[0;33m#{s}\e[0m" # yellow
859
+ #"\e[0;34m#{s}\e[0m" # blue
860
+ #"\e[0;35m#{s}\e[0m" # magenta
861
+ #"\e[0;36m#{s}\e[0m" # cyan
862
+ #"\e[0;37m#{s}\e[0m" # white
863
+ end
864
+
865
+ sys "date"
866
+ </pre>
867
+ </section>
868
+ <section class="subsection" id="how-to-disable-command-echoback">
869
+ <h3>How to disable command echoback?</h3>
870
+ <p>File: ex-quiet1.rb</p>
871
+ <pre class="language-ruby">
872
+ require 'benry/unixcmd'
873
+ include Benry::UnixCommand
874
+
875
+ <strong>BENRY_ECHOBACK = false</strong> # !!!!!
876
+
877
+ sys "date"
878
+ </pre>
879
+ <p>Result:</p>
880
+ <pre class="language-terminal">
881
+ $ ruby ex-quiet1.rb
882
+ Wed Jan 1 22:29:55 UTC 2020 # no echoback, only output
883
+ </pre>
884
+ </section>
885
+ </section>
886
+ <section class="section" id="license-and-copyright">
887
+ <h2>License and Copyright</h2>
888
+ <p>$License: MIT License $</p>
889
+ <p>$Copyright: copyright(c) 2021 kwatch@gmail.com $</p>
890
+ </section>
891
+ </section>
892
+ </main>
893
+ </body>
894
+ </html>