Linuxコマンドめも

備忘用。

## gitコマンド系

```bash:Javaの期間を絞って自分のコミット行数の確認
git log --numstat --pretty="%H" --author='hoge@foo.com' --since=2021-04-01 --until=2022-03-31 --no-merges "./*.java" | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("%d (+%d, -%d)\n", plus+minus, plus, minus)}'
```
---

```bash:コマンド名でプロセスの状態を監視
watch "ps -C {コマンド名} -o comm,pid,ppid,%cpu,ni,cls"
```

```bash:ログファイルの中身を1行ずつSJIS->UTF-8変換して出力
tail -f logfile | while read LINE ; do echo $LINE | iconv -f SJIS -t UTF-8 ; done
```

```bash:1日前までの更新ファイル検索
find . -mtime -1
```

```bash:パスワード付zip圧縮
zip -e img.zip IMG1.jpg 
```

```bash:dvd/bluerayのISOファイル作成
# blockサイズ取得
blocks=$( $(which isosize) -d 2048 /dev/cdrom )

# isoファイル作成
dd if=/dev/sr0 of=isoイメージ名 bs=2048 count=$blocks status=progress
```

```bash:ファイル分割・結合
# ファイル分割 (約100Mb単位)
split -b 100000000 bigdata.zip bigdata.zip.

# ファイル結合
cat bigdata.zip.* > bigdata.zip 
```

```bash:自分のマシンの時間ズレ確認
echo machine-time:`date +%s` nict-time:`wget -q https://3fe5a5f690efc790d4764f1c528a4ebb89fa4168.nict.go.jp/cgi-bin/json -O - | jq '.st' | sed s/\.[0-9,]*$//g`
```

```bash:ターミナルからウィンドウ開く（xwindow前提）
xdg-open .
or
gnome-open .

以下のように.bashrcに追加すると良い
alias open=xdg-open
```

```bash:sqlplus組み込みshellの基本形
#!/bin/bash

sqlplus -s / <<EOF
  select instance_name,status from v\$instance;
  exit
EOF

exit 0
```

### 定期的に同じSQLを発行し続けるshell [シェルスクリプト内でsqlplusを実行する](https://qiita.com/mon_tu/items/c85e92c019c5ee505121#%E3%83%91%E3%82%A4%E3%83%97%E3%81%A7%E6%B8%A1%E3%81%97%E3%81%A6sqlplus%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)より
```bash
#!/bin/bash

sql_alive_flg=/tmp/sql_alive.flg
touch $sql_alive_flg


(
while [ -a ${sql_alive_flg} ]
do
 echo "select instance_name,status from v\$instance;"
 sleep 5
done

echo "exit"

)|sqlplus  -s  / as sysdba

exit
```

### 見易くしたJSONをlessの色付きで確認
```bash
echo '{"name": "taro", "age": 30, "sex": "male"}' | jq -C . | less -R
```

### 数字.jpgをzero-paddingしたファイル名に変更
```bash
for i in $(ls -v) ; do  mv $i  $(printf  '%02d.jpg' $( basename $i .jpg ) ) ; done
```

### ファイル内の特定キーワードからx行分取得
```bash:logcutw.sh
#!/bin/bash
# usage: logcutw.sh filename keyword the-number-of-lines-to-get
# check args eq 3.
set -eu
: $1 $2 $3

rowno=`grep $2 $1 --line-number | head -1 | cut -f 1 -d ':'`
sed -n "$rowno, +$(($3-1))p" $1

exit 0
```

### 疑似Treeコマンド
[tree コマンドが無い環境で tree コマンドを実現](https://qiita.com/yone098@github/items/bba8a42de6b06e40983b)より

```bash
pwd;find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/|  /g'
```

### 特定キーワードでのログ監視
```bash
tail -f /var/log/xxxx/yyyy.log  | grep -P 'ERROR|FATAL' --line-buffered
または、
watch "sudo tail -10 /var/log/messages | grep 'Started'"
```

### sshのアクセス履歴表示（Ret Hat Enterprise Linux / CentOS）
```shell
sudo journalctl _SYSTEMD_UNIT=sshd.service
```

### ディスク使用量割合のグラフィカル表示
```shell
find $1 -maxdepth 1 -mindepth 1 -type d | xargs du -sk | awk '{ total += $1; pathes[$2] = $1; } END { size = 20; for (name in pathes) { ratio = pathes[name] / total; cnt = size * ratio; printf("%6.3f%% ", ratio*100); for (i = 0; i <cnt; i++) printf("="); for (i = cnt; i < size; i++ ) printf("-"); printf(" %s\n", name); } }' | sort -nr
```

### 10MBのダミーファイル作成

```shell
dd if=/dev/zero of=tempfile bs=1M count=10
または
dd if=/dev/random of=dummy.iso bs=1M count=10
```

### IPAフォントのダウンロード

```shell
sudo yum -y install ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts
```

### （メモ）JSON整形
```shell
echo '{"key1": "value1", "key2": {"key3": "value3"}}' | python -m json.tool
```

## grep o, P
```shell
grep -oP '<td><a[^>]*?>\K[\p{Katakana}ー]{5,9}(?=<)'
```
oオプション：--only-matching マッチした部分のみを抽出する
pオプション：Perl正規表現
\K：名前つき後方参照

## nvmインストール
```shell
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | sh
```

## 連番生成
```shell
seq -f "hoge%05g" 5 3 12
```
=>hoge00005
=>hoge00008
=>hoge00011

## 連番ファイル一発作成 (ブレース展開)
```shell
touch test_{1..30}.txt
touch test_{a..z}.txt
touch foo_{01..100}.txt
```

## 連番ファイルのダウンロード
```shell
seq -f http://www.example.com/img/%02g.jpg 10 | wget -w 5 --random-wait -i -
```

## 連番ファイルコピー
```shell
for i in seq -w 1 10; do cp hoge_0.png hoge_$i.png; done
seq -f "win%03g.c" 100 | xargs -I % cp win000.c %
```

## ワンライナーなwebサーバ
```shell
bash $ sudo perl -MIO::Socket -e 
  "\$s=new IO::Socket::INET
    (LocalAddr=>'localhost:80',Listen=>1);
  while(\$sock=\$s->accept()){
  while(<\$sock>=~/^GET\s+(\S+)\s+.*\$/){
  \$p=\$1;\$path=(\$p=~/^(.*\/)\$/?\$1.'index.html':\$1);}
  \$cn='';if(open(FI,'.'.\$path)){while(<FI>){\$cn.=\$_;}
  }else{\$cn='NotFound';}
  print \$sock \"HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: \".length(\$cn).\"\n\n\$cn\";\$sock->close;}
  \$s->close;"
```
[ワンライナーにかける情熱](https://qiita.com/toyohama/items/455b786e775ca60c2704#%E3%81%A4%E3%81%84%E3%81%A7%E3%81%ABweb%E3%82%B5%E3%83%BC%E3%83%90%E3%82%82%E3%81%A4%E3%81%8F%E3%81%A3%E3%81%A1%E3%82%83%E3%81%84%E3%81%BE%E3%81%97%E3%82%87%E3%81%86)
より拝借。その発想はなかった。

<br/>
#以下、[初心者向け、「上手い」シェルスクリプトの書き方メモ](https://qiita.com/m-yamashita/items/889c116b92dc0bf4ea7d)からメモ。
詳細は[そちら](https://qiita.com/m-yamashita/items/889c116b92dc0bf4ea7d)をみてね

## ファイルを 0 バイトで上書き
```shell
# 「:」は、何もしないコマンドらしい。
: > foo.log
```

## 三項演算子
```shell
# もどき
[ $foo -ge $bar ] && baz=0 || baz=1
```

## 変数初期値
```shell
# $foo に $bar を代入。但し $bar が未定義だった場合は 0 を代入
foo=${bar:-0}
# $bar が未定義だった場合、 $foo にも $bar にも 0 を代入
foo=${bar:=0}
```

## 実行ディレクトリ取得
```shell
script_dir_path=$(dirname $(readlink -f $0))
```

## 一時ディレクトリ/ファイルを作成し、中断時は、後始末
```shell
temp_file=$(mktemp)
temp_dir=$(mktemp -d)

# 後始末を定義
trap "
rm -f $temp_file
rm -rf $temp_dir
" 0
```

## お手軽引数チェック
```shell
set -eu
# 引数が3つ渡されていなければスクリプト実行中止
: $1 $2 $3
```