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