bash のメモ
といいつつLinuxコマンド全般の話
再帰的に特定の拡張子のファイルを消す
ptex2pdf -l の中間ファイルを再帰的に消す例
code:clean.sh
find . \( -name '*.log' -o -name '*.aux' -o -name '*.dvi' \) -delete
find はデフォでカレントディレクトリを見るが、 . を明示しないと再帰的には見てくれない
-o よりアクションのほうが優先度が高いので、 \( と \) でくくる必要がある
中身とは前後に1スペース空けないと「find: 無効な評価式です。二項演算子 ‘-o’ を使用していますが、前項がありません」と出る
find は簡単なものなら -name など省略できる場合もあるが、挙動が複雑なので丁寧に書いたほうが嵌まらない
markdownの2スペースでの改行を。に置き換える
code:sh
find . -name '*.md' -exec env -i sed -i /^^#.*^:alnum:\;\\{\\}。、!?\`\>\*_\|-]$/s/' *$'/。/g {} \; 先頭が 「#」 でないかつ、末尾がアルファベットや数字やコードブロック中に出現しやすい文字や句読点や感嘆符やmdの文字でないすべての行に対して、末尾の0個以上の「 」を「。」に置き換える
「! 」が「!。」に置換されたり「`」の前の「、」で終わらない行には「。」がついたりはするが、明らかに間違っているのが見て分かるし、元の文章が壊れる(元々「!」だったところが「。」になる)こともないので、適用して確認がてら細かい部分を手で直していけばよい
env -i で言語に関する環境変数を無効にする
末尾にスペースがない行にも「。」をつけるのに必要
シェルの正規表現のクラスに ] や ^ や - など [...] 内で特殊な意味を持つ文字を使いたい場合は []^-] のように、 ^ は最初の [ の直後に、 ] は [ か ^ の直後に、 - は最後の ] の直前に置く必要がある
find の -exec は ; まで(; はシェルではなく find に解釈してほしいので実際には \; と書く)の全ての {} をファイル名で置き換えるので、 \\{\\} で find に \{\} が渡るようにしている
最初から ' で文字列にしてシェルによる展開を防いで sed に渡すほうがシンプル
code:bash
find . -name '*.md' -exec env -i sed -i '/^^#>.*^:alnum:;\{\}。、!?`>)|_\*=-]$/s/ *$/。/g' {} \; これは引用や ), |, _, *, = にも対応させた例
ただしこの場合は \' や \" が効かず、 ' を扱いたいなら全体を " で囲むしかなく、 ' と " の両方を処理することはできない
配列arrayの要素を | で区切った文字列を得る
code:sh
str=(IFS=\|; echo "${array[*]}")
() でサブシェルを建て、 IFS の変更を封じ込めている
pdfを画像に変換する
code:pdf2pngs.sh
pdftoppm -png $1 ${1%.*}
sh pdf2pngs.sh 変換したいスライド.pdf のように使う
-jpeg もある、後半はコマンド置換で拡張子を除去している
echo 'pdf2pngs(){ pdftoppm -png $1 ${1%.*}; }' >> ~/.bashrc
負荷を見る
コマンドラインでやるなら ps -aur
-h でヘッダーを消して -o で自由にフォーマットを指定できるので、特に整形しなくても >> でログを出したりできる
top や htop は、 ps にUIがついて -d 秒ごとに更新されるようになった感じ
-b でUIなしで動かせ、 -o で出力を指定できる
ps のCPU使用率はCPU時間をプロセスの稼働時間で割ったもので、 top とは計算方式が違う点に注意
sar と pidstat は sysstat に入っている
sar はプロセスを指定できない代わりに、CPUの温度やファンの回転数などもとれ結果を保存できる
sadf でバイナリからTSVやXMLに変換できる
ヘッダーを出力したい場合は -dh をつけるが、 ; 区切りになってしまうので sed s/\;/,/g で変換する
pidstat は sar ライクな ps って感じ
環境変数をファイルから呼び出す
一時的に環境変数を設定してコマンドを実行する場合、 hoge=fuga command や env hoge=fuga command のようにするが、 ファイルから読ませることもできる
code:sh
$ cat foo.env
A=hoge
B=fuga
$ env cat foo.env sh -c 'echo $A$B'
hogefuga
ちなみに、 env -u 環境変数 command で指定した環境変数を、 env - command で全ての環境変数を使わずにコマンドを実行できる
echo -e
echo はPOSIXの範囲ではオプションをとらない(実装依存とされている)ので、 echo -e 'hi' は echo '-e 'hi''と解釈され、 -e hi が出力されてしまう
-e をつけなくとも \n で改行を書ける場合もあるが、これも実装依存なので printf を使うべき
ファイルの先頭と末尾に追記する
先頭に追記する場合は sed -i '1i...' file
末尾に追記する場合は echo ... >> file
両方やりたい場合は sed -i -e '1i...' -e '$a...' file
スペース区切りの文字列から一部を取り出す
スペースで区切られてる文字列から特定の部分を取り出す場合は cut が便利
ただし ls -l のように2スペースが入っている場合は tr -s ' ' | cut -d ' ' -f 2,4 のように tr と cut -d が必要
そしてこのパターンは awk だとデフォルトで区切り文字がスペースなので、awk '{print $2,$4}' と書ける
ちなみに sh -c で awk を使う場合は awk '{print \$2,\$4}' のようにエスケープする必要がある
ファイルのサイズを調べる
wc -c <file>, ls -l <file> | awk '{print $5,$9}', stat -c '%s %n' <file> はサイズとファイル名を出力する
サイズだけでいいなら stat -c %s <file>, du -bh <file> でもいけるが、stat-c, du -b はBSD系では使えない
ちなみに du -bh <file> と du -h <file> では出力が異なり、後者はディスク上のサイズを指す
wc -c は gzip -c <file> | wc -c のように実際にファイルがなくても使える
KB換算したりなど人間に分かりやすい表示が欲しい場合は ls -lh しか選択肢がない
ちなみに npx -q -p pretty-bytes-cli -c 'stat -c %s <file> | pretty-bytes' とした場合の出力は ls -lh とは異なる
これは pretty-bytes は 1000 で割っているが ls -lh は 1024 で割るため
その他
[] は test の糖衣
if は test を呼んでいるということ
ls -A
. から始まるものも表示するが、 . と .. は表示しない
ls -lh
-l の出力を見やすくする
ldconfig
共有ライブラリーの索引を更新する、 make install の後に打ったりする
-NXv で更新せず現在の状況を表示する
利用可能なロケールを表示する
locale -a
curl -sSL
L でリダイレクトに対応し、 sS でエラーだけを表示するの意味
そのままの名前で落としてくる O なども便利
#!/bin/bash -ex
e は失敗した時点で終了し、 x はデバッグ情報を逐次出力するオプション
両方指定しておけば、進行度が分かりやすく失敗してもリカバリが簡単
ちなみに #!... のことをシェバンと呼ぶ
tar xf