bashでdocker imagesの複数の空白区切りを1つの空白として扱う

Docker便利ですね。
いらなくなったDocker imagesは手動で削除していますか？
毎日起動するたびにイメージがたまっていくので定期的に掃除が必要ですよね。

インフラのコード化のためにDocker導入したのだとしたら、定期削除もbashでさくっと書いてcronで仕掛けましょう。

本稿ではDocker imagesコマンドの出力結果をbashでうまく取り扱うテクニックを紹介します。
別途、シェル化して自動運用するところまで記事化したいですが、そこまで余裕が無いのでまずはここまで。

# まずはコマンドラインで

Dockerイメージがあります。

```shell-session:出力例
[fk2000@office dockers]$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
docker.io/golang      1.6-onbuild         c4f87d4e5dc0        3 weeks ago         748.5 MB
docker.io/mysql       latest              78cdcf394b4e        4 weeks ago         400.1 MB
docker.io/mongo       latest              a3bfb96cf65e        6 weeks ago         402 MB
docker.io/ubuntu      12.04               f0d07a756afd        7 weeks ago         103.6 MB
docker.io/redis       latest              d59dc9e6d0bf        7 weeks ago         182.9 MB
docker.io/postgres    latest              0e24dd8079dc        7 weeks ago         264.8 MB
docker.io/memcached   latest              af4e963abb12        7 weeks ago         126.1 MB
docker.io/debian      latest              19134a8202e7        7 weeks ago         123 MB
```

## | cut -d' ' で単一の空白区切りで扱うと、出力結果がばらばらに
docker imagesコマンドだと行によって空白の数が違い、このままだと扱いづらいです。

```shell-session:出力例1
[fk2000@office dockers]$ docker images | cut -d' ' -f1
REPOSITORY
docker.io/golang
docker.io/mysql
docker.io/mongo
docker.io/ubuntu
docker.io/redis
docker.io/postgres
docker.io/memcached
docker.io/debian
```

```shell-session:出力例2
[fk2000@office dockers]$ docker images | cut -d' ' -f2
```

```shell-session:出力例3
[fk2000@office dockers]$ docker images | cut -d' ' -f3
```

```shell-session:出力例4
[fk2000@office dockers]$ docker images | cut -d' ' -f4







latest
```

```shell-session:出力例5
[fk2000@office dockers]$ docker images | cut -d' ' -f5






latest

```

```shell-session:出力例6
[fk2000@office dockers]$ docker images | cut -d' ' -f6
```

```shell-session:出力例7
[fk2000@office dockers]$ docker images | cut -d' ' -f7

1.6-onbuild


12.04



latest
```

```shell-session:出力例8
[fk2000@office dockers]$ docker images | cut -d' ' -f8


latest
latest

latest



```

```shell-session:出力例9
[fk2000@office dockers]$ docker images | cut -d' ' -f9
```

```shell-session:出力例10
[fk2000@office dockers]$ docker images | cut -d' ' -f10
```

## そこで、sedで整形する

cutする前にsedで空白を複数まとめてひとつに整形してしまえば単に区切りとして整頓されます。

```shell-session:出力例1
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f1
REPOSITORY
docker.io/golang
docker.io/mysql
docker.io/mongo
docker.io/ubuntu
docker.io/redis
docker.io/postgres
docker.io/memcached
docker.io/debian
```

```shell-session:出力例2
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f2
TAG
1.6-onbuild
latest
latest
12.04
latest
latest
latest
latest
```

```shell-session:出力例3
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f3
IMAGE
c4f87d4e5dc0
78cdcf394b4e
a3bfb96cf65e
f0d07a756afd
d59dc9e6d0bf
0e24dd8079dc
af4e963abb12
19134a8202e7
```

```shell-session:出力例4
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f4
ID
3
4
6
7
7
7
7
7
```

```shell-session:出力例5
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f5
CREATED
weeks
weeks
weeks
weeks
weeks
weeks
weeks
weeks
```

```shell-session:出力例6
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f6
SIZE
ago
ago
ago
ago
ago
ago
ago
ago
```

```shell-session:出力例7
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f7

748.5
400.1
402
103.6
182.9
264.8
126.1
123
```

```shell-session:出力例8
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f8

MB
MB
MB
MB
MB
MB
MB
MB
```

```shell-session:出力例9
[fk2000@office dockers]$ docker images | sed 's/\s\{1,\}/ /g'| cut -d' ' -f9
```

でもまだヘッダが値の行と一致していないくてじゃまですね。

## では、| tail -n +2 してしまいましょう。
単位の列はcutコマンドのオプションで前列の数値に結合します。（-f4-6、-f7,8 のようにハイフンやカンマで指定します）

```shell-session:出力例1
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f1
docker.io/golang
docker.io/mysql
docker.io/mongo
docker.io/ubuntu
docker.io/redis
docker.io/postgres
docker.io/memcached
docker.io/debian
```

```shell-session:出力例2
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f2
1.6-onbuild
latest
latest
12.04
latest
latest
latest
latest
```

```shell-session:出力例3
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f3
c4f87d4e5dc0
78cdcf394b4e
a3bfb96cf65e
f0d07a756afd
d59dc9e6d0bf
0e24dd8079dc
af4e963abb12
19134a8202e7

```shell-session:出力例4-6
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f4,5
3 weeks
4 weeks
6 weeks
7 weeks
7 weeks
7 weeks
7 weeks
7 weeks
```

```shell-session:出力例7,8
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f7,8
748.5 MB
400.1 MB
402 MB
103.6 MB
182.9 MB
264.8 MB
126.1 MB
123 MB
```

```shell-session:出力例9
[fk2000@office dockers]$ docker images | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f9
```

# まとめ
シェルでrmiするよりも、Docker1.13バージョンのdocker systemコマンドでやったほうが楽ですね。

# 追記

シェル化して、cronでぶん回してディスクスペースに余裕ができましためでたしめでたし。

```
#!/bin/sh

TODAY=$(date +%Y%m%d)

  START_LOG="#time:`date +%Y%m%d_%H-%M-%S` [start] "
  echo ${START_LOG} 2>&1 | tee -a ./logs/$TODAY.log

  echo "before:" && docker images ${DOCKER_ENDPOINT}/${SERVICE} | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f1-3 
  
  # デリミタを退避 
  IFS_BACKUP=$IFS
  IFS=$'\n'

  # 2世代以上のdocker imagesのimageIDを配列に格納
  ARGS=($(docker images ${DOCKER_ENDPOINT}/${SERVICE} | tail -n +4 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f3))
  echo "${ARGS[@]}" 2>&1 | tee -a ./logs/$TODAY.log
  if [ ${#ARGS[*]} -gt 0 ] ; then
      #echo "${ARGS[@]}"
      docker rmi "${ARGS[@]}" 
  else
      echo "No arguments supplied" 2>&1 | tee -a ./logs/$TODAY.log
  fi
  
  # デリミタを元に戻す
  IFS=$IFS_BACKUP

  echo "after:" && docker images ${DOCKER_ENDPOINT}/${SERVICE} | tail -n +2 | sed 's/\s\{1,\}/ /g'| cut -d' ' -f1-3 

  END_LOG="#time:`date +%Y%m%d_%H-%M-%S` [end] "
  echo ${END_LOG} 2>&1 | tee -a ./logs/$TODAY.log

```