全力で怠けたい

怠けるために全力を尽くしたいブログ。

date コマンドの自分的チートシート。

date コマンドの自分的チートシートをメモしておく。

date コマンドのバージョン。

$ date --version
date (GNU coreutils) 9.0
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by David MacKenzie.

date コマンドのチートシート

MacGNU date を使う

macOS にインストールされている date コマンドは BSD 版のため、GNU date を使うためには自分でインストールする必要がある。 brewcoreutils をインストールすると楽。

$ brew install coreutils

brew でインストールした GNU のコマンドは g というプリフィックスが付いており、たとえば date コマンドなら gdate というコマンドになっている。 g を打つのが面倒くさいときは alias date='gdate' のようにエイリアスを付けるとよい。 ただ、 date のほかにも多数のコマンドがインストールされるので、個別にエイリアスを付けるのは少々面倒くさい。 そこで、GNU コマンドがインストールされたパスを優先して検索するように、シェルの設定ファイルなどで PATH 変数を設定してしまうのがよいと思う。

$ PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"

オプションを指定せずに実行する

オプションを指定せずに実行すると現在日時をロケールに基づくフォーマットで表示する。

$ date
2022年  6月 14日 水曜日 20:03:48 JST

日時をロケールに基づくフォーマットで表示する

LC_TIME を指定して実行すると、現在日時を指定したロケールに基づくフォーマットで表示する。

$ date
2022年  6月 14日 水曜日 20:03:48 JST

$ LC_TIME=en_US date
Wed Jun 14 20:03:48 JST 2022

日時を任意のフォーマットで表示する

+FORMAT を指定して実行すると、現在日時を指定したフォーマットで表示する。 指定可能なフォーマットは man date にて確認できる。

$ date +'%Y/%m/%d %H:%M:%S (%z)'
2022/06/14 20:03:48 (+0900)

日時を ISO 8601 フォーマットで表示する

-I<精度>, --iso-8601=<精度> を指定すると、現在日時を ISO 8601 フォーマットで表示する。 +FORMAT で ISO 8601 フォーマットを指定しても同じことができるけど、こちらのほうがタイプ数が少なくて楽。

$ date -Idate
2022-06-14

$ date -Iseconds
2022-06-14T20:03:48+09:00

$ date -Ins
2022-06-14T20:03:48,000000000+09:00

日時を RFC 3339 フォーマットで表示する

--rfc-3339=<精度> を指定すると、現在日時を RFC 3339 フォーマットで表示する。 +FORMATRFC 3339 フォーマットを指定しても同じことができるけど、こちらのほうがタイプ数が少なくて楽。 精度は date, seconds または ns を指定できる。

$ date -f - --rfc-3339=date
2022-06-14

$ date --rfc-3339=seconds
2022-06-14 20:03:48+09:00

$ date --rfc-3339=ns
2022-06-14 20:03:48.000000000+09:00

任意のタイムゾーンでの日時を表示する

TZ=<タイムゾーン> を指定すると、指定したタイムゾーンでの現在日時を表示する。

$ TZ='Asia/Tokyo'
2022年  6月 14日 火曜日 20:03:48 JST

$ TZ=UTC date
2022年  6月 14日 火曜日 11:03:48 UTC

UTC での日時を表示する

-u, --utc または --universal を指定すると UTC での現在日時を表示する。 TZ=UTC を指定するのと同じことができるけど、こちらのほうがタイプ数が少なくて楽。

$ date -u
2022年  6月 14日 火曜日 11:03:48 UTC

指定した日時を表示する

-d, --date で日時を指定すると、指定した日時を表示する。

$ date -d '2022-02-28 01:23:45+09:00'
2022年  2月 28日 月曜日 01:23:45 JST

日時はかなり柔軟に指定でき、何日前、何ヶ月後といった日時も表示できる。

# 4日前
$ date -d '2022-02-28 01:23:45+09:00 4 days ago'
2022年  2月 24日 木曜日 01:23:45 JST

# 1ヶ月後
$ date -d '2022-02-28 01:23:45+09:00 next month'
2022年  3月 28日 月曜日 01:23:45 JST

ファイルから読み取った日時を表示する

-f, --file を指定するとファイルから読み取った日時を表示する。

$ cat date.txt
2022-02-28 01:23:45+09:00
2022-03-31 01:23:45+09:00

$ date -f date.txt
2022年  2月 28日 月曜日 01:23:45 JST
2022年  3月 31日 木曜日 01:23:45 JST

標準入力から読み取った日時を表示する

-f, --file にて - を指定すると標準入力から読み取った日時を表示する。

$ cat date.txt | date -f-
2022年  2月 28日 月曜日 01:23:45 JST
2022年  3月 31日 木曜日 01:23:45 JST

JST から UTC に変換する

$ date -Iseconds
2022-06-14T20:03:48+09:00

$ date -Iseconds | date -f- -u -Iseconds
2022-06-14T11:03:48+09:00

UTC から JST に変換する

$ date -u -Iseconds
2022-06-14T11:03:48+09:00

$ date -u -Iseconds | TZ='Asia/Tokyo' date -f- -u
2022-06-14T20:03:48+09:00

任意のタイムゾーンから別のタイムゾーンに変換する

# CST (中国標準時) は +08:00
$ TZ='Asia/Shanghai' date -Iseconds
2022-06-14T19:03:48+08:00

# AEST (オーストラリア東部標準時) は +10:00
$ TZ='Australia/Brisbane' date -Iseconds
2022-06-14T21:03:48+10:00

$ TZ='Asia/Shanghai' date -Iseconds | TZ='Australia/Brisbane' date -f- -Iseconds
2022-06-14T21:03:48+10:00

エポック秒を表示する

+%s を指定して実行すると エポック秒 を表示する。

$ date +'%s'
1655204628

$ date -Iseconds | date -f- +'%s'
1655204628

エポック秒を任意のフォーマットで表示する

$ echo '@1655204628' | date -f- -Iseconds
2022-06-14T20:03:48+09:00

$ echo '@1655204628' | date -f- +'%Y/%m/%d %H:%M:%S (%z)'
2022/06/14 20:03:48 (+0900)

月末日を表示する

月初日 (1日) に1ヶ月を足してから1日引くと月末日を求めることができる。

$ date -d '2022-02-01 1 months 1 days ago'
2022年  2月 28日 月曜日 00:00:00 JST

$ date -d '2022-03-01 1 months 1 days ago'
2022年  3月 31日 木曜日 00:00:00 JST

sed と組み合わせると入力された日付の月末日を簡単に求めることができる。

$ echo '2022-02-15' | sed -E 's/-[0-9]+$/-01 1 months 1days ago/' | date -f-
2022年  2月 28日 月曜日 00:00:00 JST

$ echo '2022-03-15' | sed -E 's/-[0-9]+$/-01 1 months 1days ago/' | date -f-
2022年  3月 31日 木曜日 00:00:00 JST

sort コマンドが human readable な数値をソートできて便利。

sort コマンドが human readable な数値をソートできて便利なのでメモしておく。

Ubuntu のバージョン。

$ cat /etc/os-release | grep VERSION_ID
VERSION_ID="20.04"

sort コマンドで human readable な数値をソートする

自分はディレクトリごとのディスク使用量を human readable な形式で表示してザッと見るには du -sh コマンドを実行する。 du コマンドを -h オプションを指定して実行すると 892K みたいに人間が読みやすい形式で表示してくれるけど、ディスク使用量の昇順でソートしようと sort コマンドを通しても期待どおりにはソートしない。

$ ls
a/ b/ c/ d/

$ du -sh ./*
892K    ./a
1.6M    ./b
31M ./c
4.0K    ./d

$ du -sh ./* | sort
1.6M    ./b
31M ./c
4.0K    ./d
892K    ./a

sort -n みたいに文字列を数値と見なしてソートしてもやっぱり期待どおりにはソートしない。

$ du -sh ./* | sort -n
1.6M    ./b
4.0K    ./d
31M ./c
892K    ./a

実は sort コマンドは human readable な数値をソートする -h オプション (--human-numeric-sort オプション) が用意されていて、このオプションを使うと human readable な数値を簡単にソートできる。 すごく便利。

$ du -s ./* | sort -h
4.0K    ./d
892K    ./a
1.6M    ./b
31M ./c

jq コマンドの Alternative operator: `//` が欠落値を代替できて便利。

jq コマンドの Alternative operator: // が欠落値を代替できて便利なのでメモしておく。

jq のバージョン。

$ jq --version
jq-1.6

使い方

学生の名簿がこんな感じの JSON になってるとき、age フィールドがあったら age フィールドを出力して age フィールドがなかったら 2022 - year_of_birth フィールドの計算結果を出力したい要件があるとする。

こんなときは // を使うととても簡潔に記述できる。便利。

$ cat students.json | jq
{
  "students": [
    {
      "name": "Alice",
      "age": 20
    },
    {
      "name": "Bob",
      "year_of_birth": 2001
    }
  ]
}

$ cat students.json | jq '.students[] | .age // 2022 - .year_of_birth'
20
21

age フィールドがなかったら 2022 - year_of_birth フィールドの計算結果を age フィールドに入れ込んだりもできる。

$ cat students.json | jq '.students[] | .age = (.age // 2022 - .year_of_birth)'
{
  "name": "Alice",
  "age": 20
}
{
  "name": "Bob",
  "year_of_birth": 2001,
  "age": 21
}

一応、if-then-else を使っても同じことができる。

$ cat students.json | jq '.students[] | if .age then .age = .age else .age = 2022 - .year_of_birth end'
{
  "name": "Alice",
  "age": 20
}
{
  "name": "Bob",
  "year_of_birth": 2001,
  "age": 21
}

Ubuntu で gawk を使う方法。

Ubuntugawk を使う方法をメモしておく。

はじめに

Ubuntuawk を使ってたらなんか期待している挙動にならないみたいで、調べてみたら Ubuntu はデフォでは gawk は入ってなくて mawk が入ってるよう。 自分は gawk を使いたかったので gawk を使えるようにしたので、その方法をメモしておく。

Ubuntu のバージョン。

$ cat /etc/os-release | grep VERSION_ID
VERSION_ID="20.04"

Ubuntu はデフォでは gawk は入っていなくて mawk が入ってる

/bin/awk/etc/alternatives/awk へのシンボリックリンクになっていて、/etc/alternatives/awk/usr/bin/mawk へのシンボリックリンクになっている。

$ which awk
/usr/bin/awk

$ ls -l /bin/awk
lrwxrwxrwx 1 root root 21 Mar  7  2021 /bin/awk -> /etc/alternatives/awk

$ ls -l /etc/alternatives/awk
lrwxrwxrwx 1 root root 13 Dec  1 01:16 /etc/alternatives/awk -> /usr/bin/mawk

/bin/awk の実体は ls コマンドでシンボリックリンクを追う方法以外にも update-alternatives コマンドを実行することでも表示できる。

$ update-alternatives --display awk
awk - auto mode
  link best version is /usr/bin/mawk
  link currently points to /usr/bin/mawk
  link awk is /usr/bin/awk
  slave awk.1.gz is /usr/share/man/man1/awk.1.gz
  slave nawk is /usr/bin/nawk
  slave nawk.1.gz is /usr/share/man/man1/nawk.1.gz
/usr/bin/mawk - priority 5
  slave awk.1.gz: /usr/share/man/man1/mawk.1.gz
  slave nawk: /usr/bin/mawk
  slave nawk.1.gz: /usr/share/man/man1/mawk.1.gz

ちなみに mawk は --version オプションはないけど -W version オプションを指定して実行するとバージョンが表示する。

$ awk --version
awk: not an option: --version

$ awk -W version
mawk 1.3.4 20200120
Copyright 2008-2019,2020, Thomas E. Dickey
Copyright 1991-1996,2014, Michael D. Brennan

random-funcs:       srandom/random
regex-funcs:        internal
compiled limits:
sprintf buffer      8192
maximum-integer     2147483647

gawk をインストールする

gawkUbuntu にインストールして使えるようにしていく。 apt update コマンドと apt install gawk コマンドを実行するだけ。

$ sudo apt update
$ sudo apt install gawk -y

$ /bin/gawk --version
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
Copyright (C) 1989, 1991-2019 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

ls コマンドで /etc/alternatives/awkシンボリックリンク先を表示すると /usr/bin/gawk になってるので、単に awk コマンドを実行すると gawk が動くようになってる。

$ ls -l /etc/alternatives/awk
lrwxrwxrwx 1 root root 13 Dec  1 01:39 /etc/alternatives/awk -> /usr/bin/gawk

gawk と mawk (とその他の awk) を使い分ける

gawk と mawk を使い分ける方法だけど、gawk を使うときは /usr/bin/gawk を使うようにして mawk を使うときは /usr/bin/mawk を使うようにすればよい。

あと単に awk コマンドを実行するときにシステムにインストールしているどの awk を実行するかは update-alternatives コマンドで切り替えることができる。 たとえばこういう表示になるときは 1 を入力したら単に awk コマンドを実行すると usr/bin/gawk が実行するようになるし、2 を入力したら単に awk コマンドを実行すると usr/bin/mawk が実行するようになる。

$ sudo update-alternatives --config awk
There are 2 choices for the alternative awk (providing /usr/bin/awk).

  Selection    Path            Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gawk    10        auto mode
  1            /usr/bin/gawk    10        manual mode
  2            /usr/bin/mawk    5         manual mode

Press <enter> to keep the current choice[*], or type selection number:

参考サイト

MySQL で SQL を記述した外部ファイルから実行する方法。

MySQL というか mysql コマンドで SQL を記述した外部ファイルから実行する方法をメモしておく。

mysql コマンドのバージョン。5.7 とか 5.6 でも同じやり方が使える。

$ mysql --version
mysql  Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)

動作を確認する用の適当なテーブルとデータを作っておく。 あと認証にかかわるオプション -u とかは記載は省略していく。

mysql> create database mydb;
Query OK, 1 row affected (0.01 sec)

mysql> use mydb;
Database changed

mysql> create table my_table(id int);
Query OK, 0 rows affected (0.04 sec)

mysql> insert into my_table values(1);
Query OK, 1 row affected (0.02 sec)

SQL を記述した外部ファイルから実行する方法

SQL を記述したファイルを mysql コマンドの標準入力にリダイレクトする

mysql コマンドは SQL ステートメントを標準入力から読み込んで実行するので、SQL を記述したファイルを mysql コマンドの標準入力にリダイレクトする。

$ cat select.sql
use mydb;
select * from my_table;

$ mysql -t < select.sql
+------+
| id   |
+------+
|    1 |
+------+

SQL を記述したファイルをパイプで mysql コマンドの標準入力に接続する

mysql コマンドは SQL ステートメントを標準入力から読み込んで実行するので、SQL を記述したファイルをパイプで mysql コマンドの標準入力に接続する。 自分がネットワーク越しに巨大な SQL ファイルを取得して実行するとかはだいたいこれ。

$ cat select.sql | mysql -t
+------+
| id   |
+------+
|    1 |
+------+

source コマンドでSQL を記述したファイルを読み込む

mysql コマンドの対話モードで source コマンドを実行すると外部ファイルを読み込んで実行する。

$ cat select.sql
use mydb;
select * from my_table;

$ pwd
/home/bob

$ mysql

mysql> source /home/bob/select.sql
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

source コマンドは相対パスを指定してもちゃんとファイルを読み込んでくれる。

mysql> source ./select.sql
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

さらに source コマンドは ~ をホームディレクトリのパスに展開してくれるのでこんな感じにも使える。

mysql> source ~/select.sql
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

あと source コマンドは \. でも実行できる。source とタイプするのがだるいときは \. とタイプすると4文字分を省略できる。

mysql> \. ~/select.sql
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

参考サイト

Arch Linux で日本語の man pages を見られるようにする方法。

はじめに

自分は普段は man pages は英語のものを読むことが多いけど英語だとどうしても読む速度が遅くなるので、たまにザッと目を通したいときは日本語の man page を見たりする。 Arch Linux はデフォルトでは日本語の man pages は見れないけど、日本語に翻訳した man pages をインストールすると日本語の man pages を見れるようになる。

日本語の man pages を見れるようにする方法

AUR の man-pages-ja パッケージをインストールすると日本語の man pages を見れるようになる。

AUR のパッケージは base-devel グループがインストールされているのを前提としているので先にインストールしておく。

$ sudo pacman -S --needed base-devel

downgrade のリポジトリをクローンして makepkg -si コマンドを実行すると、makepkg コマンドが自動でソースコードをダウンロード、pacman で依存関係を解決、コンパイルしてパッケージ化してパッケージをインストールする。

$ git clone https://aur.archlinux.org/man-pages-ja.git
$ cd man-pages-ja
$ makepkg -si

man-pages-ja パッケージをインストールしたら、たとえば man ls みたいにして ls コマンドの日本語の man pages を見ることができる。

参考サイト

man ページ - ArchWiki

bash と sh の test コマンドの条件式で使える演算子のチートシート。

はじめに

ちょっとしたことはシェルで済ませるけど、条件分岐をするのに使う test コマンドで使える演算子をたまに忘れるのでメモしておく。

test コマンドの条件式で使える演算子チートシート

文字列を条件判断する演算子

演算子 条件式 説明
-z -z 文字列 文字列が空文字列なら真
-n -n 文字列 文字列が空文字列でなければ真
= 文字列1 = 文字列2 文字列1と文字列2が同じなら真
== 文字列1 == 文字列2 文字列1と文字列2が同じなら真。※bash のみ
!= 文字列1 != 文字列2 文字列1と文字列2が異なるなら真
< 文字列1 < 文字列2 文字列1が辞書順で文字列2より小さければ真
> 文字列1 > 文字列2 文字列1が辞書順で文字列2より大きければ真

数値を条件判断する演算子

演算子 条件式 説明
-eq 数値1 -eq 数値2 数値1と数値2が等しければ真
-ne 数値1 -ne 数値2 数値1と数値2が等しくなければ真
-lt 数値1 -lt 数値2 数値1が数値2より小さければ真
-le 数値1 -le 数値2 数値1が数値2以下ならば真
-gt 数値1 -gt 数値2 数値1が数値2より大きければ真
-ge 数値1 -ge 数値2 数値1が数値2以上ならば真

ファイルを条件判断する演算子

演算子 条件式 説明
-d -d ファイル ファイルがディレクトリなら真
-e -e ファイル ファイルが存在するなら真
-f -f ファイル ファイルが通常ファイルなら真
-g -g ファイル ファイルがセットグループ ID されていたら真
-h -h ファイル ファイルがシンボリックリンクなら真
-k -k ファイル ファイルのスティッキービットがセットしていたら真
-p -p ファイル ファイルが名前付きパイプなら真
-r -r ファイル ファイルが読み込み可能なら真
-s -s ファイル ファイルサイズが 0 よりも大きければ真
-t -t ファイルディスクリプタ ファイルディスクリプタが端末なら真
-u -u ファイル ファイルがセットユーザー ID されていたら真
-w -w ファイル ファイルが読み込み可能なら真
-x -x ファイル ファイルが実行可能なら真
-S -S ファイル ファイルがソケットなら真
-N -N ファイル ファイルの更新日時がアクセス日時以降なら真
-nt ファイル1 -nt ファイル2 ファイル1の更新日時がファイル2の更新日時より新しかったら真
-ot ファイル1 -ot ファイル2 ファイル1の更新日時がファイル2の更新日時より古かったら真
-ef ファイル1 -ef ファイル2 ファイル1とファイル2の i ノードが同じなら真

論理演算子

演算子 条件式 説明
! ! 条件式 条件式の評価結果を否定する。つまり条件式が偽なら真
-a 条件式1 -a 条件式2 条件式1と条件式2が両方とも真なら真
-o 条件式1 -o 条件式2 条件式1と条件式2のどちらかが真なら真