今年自分が初めて知った小技やtipsをまとめてみた

# 概要

年末なので、今年1年間で初めて知った小技やテクニックをまとめてみました。軽い読み物として見て頂き、「こんなのあるんだ！」と思ってもらえたら幸いです。

## Shell script

### `$'\t'`（タブの表現）

タブ文字を直接打つ他にも、`$'\t'`と表現できます

```tsv:test.tsv
aaa bbb
123 456
```

```bash
awk -F $'\t' '{print $2}' test.tsv
```

### awkでtsvを読む

awkのオプション`-F`にタブ文字を指定します

```bash
awk -F $'\t' '{print $2}' test.tsv
```

### `|&`（標準出力とエラー出力両方をパイプで渡す）

下記は、標準出力とエラー出力を標準出力とファイルへ書き込みます

```bash
./sample.sh |& tee stdout_stderr.log
```

### ImageMagickで サムネイルを作る

横500px、縦180pxのサムネイルを生成します。

```bash
convert -define jpeg:size=500x180 test.jpg \
  -auto-orient -thumbnail 500x500 -unsharp 0x.5 test_thumbnail.jpg
```

### parallelで並列処理

上記のサムネイル生成コマンドを並列処理します。

```bash
# とある場所に画像のみを格納しているディレクトリがあるとします。
cd path/to/image_dir

find . -type f -print0 | parallel --null \
  convert -define jpeg:size=500x180 {} \
  -auto-orient -thumbnail 500x500 -unsharp 0x.5 {}_thumbnail.jpg 2>>../err.log
```

### テキストファイルの改行コードを変更（CRLF -> LF）

sedは処理結果を標準出力に出力しますが、オプション`-i`を使用することで読み込んだファイルに出力できます（上書き保存）。

```txt:target.txt
a
b
c
```

```bash
od -c target.txt
# 下記が出力される
# 0000000   a  \r  \n   b  \r  \n   c  \r  \n
# 0000011
```

```bash
# \r\n -> \n
sed -i -z 's/\r\n/\n/g' target.txt
```

```bash
od -c target.txt
# 下記が出力される
# 0000000   a  \n   b  \n   c  \n
# 0000006
```

### ssh越しにtar.gzファイルを渡す

下記事象が重なっている状況があり、このコマンドは重宝しました。

- リモートサーバのストレージが枯渇しているが、圧縮ファイルなら置けそう
- ローカルのストレージも枯渇しており、手元にtarアーカイブを作成できない
- リモートサーバでは、rsyncなどを勝手にインストールできない

```bash
tar zcf - target_dir/ | ssh my_server.example.com "cat >target_dir.tar.gz"
```

長時間接続していると、sshがtimeoutしてしまうので対策したコマンド

```bash
tar zcf - target_dir/ |
  ssh -o TCPKeepAlive=yes -o ServerAliveInterval=60 -o ServerAliveCountMax=3 \
  user@my_server.example.com "cat >target_dir.tar.gz"
```

### ファイルリストからtarアーカイブを作成

tarコマンドにて、`--files-from`オプションを指定して、圧縮したいファイルのパスを記述したファイルを指定して圧縮できます。

```bash
# サンプルとして下記ファイルを作成
mkdir test
touch file1.txt test/file2.txt

# ファイルリストを作った
cat files.txt 
# file1.txt
# test/file2.txt

tar zcf target_dir.tar.gz --files-from files.txt
```

### ext4では`*`や`\`もファイル名として使用可能

ext4（Linuxで採用されているファイルシステム）では、ファイル名にNULL(`\0`)と`/`以外の文字を使用できます。

```bash
touch '*' '\'

# 他にもこんなものも使用可能
touch '|' '>' '<' '?'

# 制御文字も？
```

ここで、ファイル名としての`'*'`と、ワイルドカードとしての`*`に注意してください。ファイル名ならクォーテーションで囲みます。下記はディレクトリ'*'以下のファイルを出力したい時のコマンドです。

```bash
mkdir '*'
cd '*'
touch file1 file2 file3
cd ../

echo '*'/*
# 出力例: */file1 */file2 */file3
```

<!--
## データベース

### Create Indexが終わらない・・・

### mysqldumpslow

### 分析関数（over, partition）
-->

## Sqlite3

sqlite3には、システムの運用・保守をやっていて、マスタ系データの整備などで使用しました。csvやらtsvやら、表データをサクッと管理したいときにかなり助けてもらいました。

### csvをsqlite3に取り込む

ヘッダーのあるCSVを取り込みます。

```bash
sqlite3 -separator ',' "db.sqlite3" ".import 'data.csv' items"
# ここで、 data.csv は取り込みたいcsvファイル名、itemsは新規作成するテーブル名

sqlite3 "db.sqlite3" "SELECT * FROM items limit 10"
```

文字コードがshift-jisのCSVファイルを取り込む場合は、iconvで変換し、標準入力経由で取り込むことができます。

```bash
iconv -f cp932 -t utf-8 shift-jis-data.csv |
  sqlite3 -separator ',' "db.sqlite3" ".import '| cat -' items"
```

<!--
## PHP

### 配列のキーがintへキャストされる
-->

## サーバ

<!--
### SELinuxファイルに”.”が付く
-->

### 秘密鍵から公開鍵生成

特定の鍵でgit cloneなどを行えるよう、CodeCommitやらGithubやらに公開鍵を登録したい時がありました。しかしその鍵は秘密鍵しかなく、どうしようと思った時に調査して知ったコマンドです。

```bash
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
```

### 公開鍵からフィンガープリント出力

例えば、`authorized_keys`の一番上の公開鍵に対するフィンガープリントを出力するコマンドです。

```bash
head -n 1 ~/.ssh/authorized_keys | tail -n 1 | ssh-keygen -lf -
```

## Windows

### Windows時間(NT タイムエポック)

Unix時間、エポック秒などは聞いたことありましたが、Windowsは別にあるんですね。

> Unix タイムスタンプでは、1970年1月1日0時0分0秒からの秒数で表されているタイムスタンプですが、Windows では、1601年1月1日0時0分からの100ナノ秒単位で表されています。

以上です。