今日、ふとしたことで moreutils
というものの存在を知った。ニッチだが使いこなすと便利そうなコマンド郡だったので一通りすべて触ってみることにする。最近お仕事で shell のワンライナーを書くことが多々あるので有効活用するぞ。
今回扱うのはCentOS7で入る moreutils
にする。Ubuntuでも多分同じ中身だろう(未確認)
かなり参考にしました。アウトプットのために内容が被っていても投稿
$ sudo yum install moreutils
$ rpm -qi moreutils
Name : moreutils
Version : 0.49
Release : 2.el7
Architecture: x86_64
Install Date: Tue 13 Nov 2018 03:55:29 AM JST
Group : Applications/System
Size : 155340
License : GPLv2
Signature : RSA/SHA256, Tue 04 Mar 2014 12:35:02 PM JST, Key ID 6a2faea2352c64e5
Source RPM : moreutils-0.49-2.el7.src.rpm
Build Date : Wed 26 Feb 2014 07:58:44 PM JST
Build Host : buildvm-21.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager : Fedora Project
Vendor : Fedora Project
URL : http://kitenet.net/~joey/code/moreutils/
Summary : Additional unix utilities
Description :
This is a growing collection of the unix tools that nobody thought
to write thirty years ago.
So far, it includes the following utilities:
- isutf8: check if a file or standard input is utf-8
- sponge: soak up standard input and write to a file
- ts: timestamp standard input
- vidir: edit a directory in your text editor
- vipe: insert a text editor into a pipe
- combine: combine the lines in two files using boolean operations
- ifdata: get network interface info without parsing ifconfig output
- pee: tee standard input to pipes
- zrun: automatically uncompress arguments to command
- mispipe: pipe two commands, returning the exit status of the first
- lckdo: execute a program with a lock held
- ifne: run a program if the standard input is not empty
- parallel: run multiple jobs at once (contained in moreutils-parallel sub package)
- chronic: runs a command quietly, unless it fails
command
rpm -qi moreutils
の簡易説明
雰囲気概要和訳
使用例
のような形で書いていく。
isutf8
check if a file or standard input is utf-8
ファイルか標準入力が utf-8 であるか判定する
$ echo "日本語" | isutf8 ; echo $?
0
$ echo "日本語" | nkf -Ws | isutf8 ; echo $?
stdin: line 1, char 1, byte offset 6: invalid UTF-8 code
1
文字コードがutf8でないファイルにだけ特定の処理をするとか
$ ls
0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
$ file *
0.txt: Non-ISO extended-ASCII text
1.txt: UTF-8 Unicode text
2.txt: UTF-8 Unicode text
3.txt: UTF-8 Unicode text
4.txt: UTF-8 Unicode text
5.txt: UTF-8 Unicode text
6.txt: UTF-8 Unicode text
7.txt: Non-ISO extended-ASCII text
8.txt: UTF-8 Unicode text
9.txt: UTF-8 Unicode text
$ for FILE in `ls`; do isutf8 $FILE 1>/dev/null || echo $FILE; done
0.txt
7.txt
sponge
soak up standard input and write to a file
標準入力を全て受け取った後にファイルへ出力する(標準出力も可)
$ cat file1
1
8
9
4
$ cat file1 | sort > file1
$ cat file1
(empty)
$ cat file2
1
8
9
4
$ cat file2 | sort | sponge file2
$ cat file2
1
4
8
9
早速だがワンライナーでの使用例が思いつかない。使い捨てのワンライナーでわざわざ入力と出力を同じファイルにする理由があるのだろうか。
ts
timestamp standard input
標準入力で受け取った各行にタイムスタンプを追加して出力する
$ seq 5 | ts
Nov 16 00:05:01 1
Nov 16 00:05:01 2
Nov 16 00:05:01 3
Nov 16 00:05:01 4
Nov 16 00:05:01 5
strftime形式で指定するとそのフォーマットで出力する。 "%.S"
でより細かい時間を確認できる
$ seq 5 | ts "%H:%M:%.S"
00:25:36.169158 1
00:25:36.169227 2
00:25:36.169265 3
00:25:36.169299 4
00:25:36.169333 5
-r
オプションで現在との差分を確認できる。ログを読むのが楽になるかもしれない
$ sudo tail /var/log/secure
(略)
Nov 16 00:29:17 localhost sudo: cat : TTY=pts/16 ; PWD=/home/cat/workspace/tmp ; USER=root ; COMMAND=/bin/tail /var/log/secure
Nov 16 00:29:47 localhost sudo: cat : TTY=pts/16 ; PWD=/home/cat/workspace/tmp ; USER=root ; COMMAND=/bin/tail /var/log/secure
$ sudo tail /var/log/secure | ts -r
(略)
36s ago localhost sudo: cat : TTY=pts/16 ; PWD=/home/cat/workspace/tmp ; USER=root ; COMMAND=/bin/tail /var/log/secure
6s ago localhost sudo: cat : TTY=pts/16 ; PWD=/home/cat/workspace/tmp ; USER=root ; COMMAND=/bin/tail /var/log/secure
right now localhost sudo: cat : TTY=pts/16 ; PWD=/home/cat/workspace/tmp ; USER=root ; COMMAND=/bin/tail /var/log/secure
vidir
edit a directory in your text editor
ディレクトリやファイルの名前をテキストエディタ経由で編集できる
$ ls
1 2 3 4 5
$ vidir
1 ./1
2 ./2
3 ./3
4 ./4
5 ./5
↓ 編集して終了(:wq)
1 ./1001
2 ./1002
3 ./1003
4 ./1004
5 ./1005
$ ls
1001 1002 1003 1004 1005
例えば、深いディレクトリに隠れているファイル達に対してそのパスをprefixとしてつけつつmvすることができる。
$ ls
1 out
$ ls 1/*/*
1/1/a 1/1/b 1/1/c 1/2/a 1/2/b 1/2/c
$ vidir 1/*/*
1 ./1/1/a
2 ./1/1/b
3 ./1/1/c
4 ./1/2/a
5 ./1/2/b
6 ./1/2/c
↓ 編集して終了(:wq)
1 out/1-1-a
2 out/1-1-b
3 out/1-1-c
4 out/1-2-a
5 out/1-2-b
6 out/1-2-c
$ ls out/
1-1-a 1-1-b 1-1-c 1-2-a 1-2-b 1-2-c
$ ls 1/*/*
ls: cannot access 1/*/*: No such file or directory
vipe
insert a text editor into a pipe
受け取った標準入力をテキストエディタで編集して次のパイプに渡すことができる
特に説明不要なので使用例だけ。
command1 | vipe | command2
combine
combine the lines in two files using boolean operations
2つのファイルの中身をブール演算を用いて結合する
$ cat a.txt
banana
apple
orange
$ cat b.txt
banana
suica
orange
strawberry
$ combine a.txt and b.txt
banana
orange
$ combine a.txt not b.txt
apple
$ combine a.txt or b.txt
banana
apple
orange
banana
suica
orange
strawberry
$ combine a.txt xor b.txt
apple
suica
strawberry
diff
を取ってから差分を取り回していたのが直接できるかな。
ifdata
get network interface info without parsing ifconfig output
ネットワーク情報を簡潔な形式で出力する
他にもオプションが大量にある。インターフェイス名は ifdata
で取得できないので予め把握しておくか、 ip link show
等で持ってくる必要がある
$ ifdata -pa eth0
10.0.2.15
pee
tee standard input to pipes
標準入力を受け取りパイプに流すtee
説明からは分かりづらいが、受け取った標準入力を複数のパイプに流すことができる。その際は |
でパイプを書くのではなく引数にコマンドとして実行する文字列を渡す。 tee
は標準入力を標準出力とファイル出力の2つに流すが、 pee
は複数のパイプに流せる、ということか。
$ echo "12345" | pee "xargs echo" "rev | xargs echo" "factor"
12345
54321
12345: 3 5 823
zrun
automatically uncompress arguments to command
引数に渡された圧縮ファイルを自動で展開してコマンドを実行する
対応している拡張子は gz
, bz2
, xz
, lzma
, lzo
展開した一時ファイルは /tmp
に作成される模様
$ ls
file.gz
$ zrun cat file.gz
abcde
12345
QWERT
%&#~=
$ ls
file.gz
mispipe
pipe two commands, returning the exit status of the first
2つのコマンドをパイプでつなげるが、終了ステータスは1番目のコマンドの値を返却する
$ mispipe "echo hoge; exit 1" "xargs echo" ; echo $?
hoge
1
lckdo
execute a program with a lock held
ロックを掛けつつプログラムを実行する
マルチプロセスで同一のフィアルに変更を与えないようにファイルをロックすることができる。現在のLinuxには flock
という同じことができるコマンドが存在するためdeprecatedになっている。
ifne
run a program if the standard input is not empty
標準入力が空でない場合にコマンドを実行する
$ echo -n "" | ifne date
$ echo -n "hoge" | ifne date
Fri Nov 16 09:43:23 JST 2018
ifne
には -n
オプションがあり、つけると挙動が逆転する。ただし、本来の標準出力が出力される模様
$ echo -n "" | ifne -n date
Fri Nov 16 09:44:55 JST 2018
$ echo -n "hoge" | ifne -n date
hoge
parallel
run multiple jobs at once (contained in moreutils-parallel sub package)
パッケージには含まれているようだが、コマンド自体は存在しなかった。謎
chronic
runs a command quietly, unless it fails
コマンドを実行し、失敗した場合のみ標準出力と標準エラー出力に出力を行う
$ chronic sh -c "echo hoge; exit 1"
hoge
$ chronic sh -c "echo hoge; exit 0"