シェル芸(シェルコマンド)の使い方を覚えるための課題を作ってみた。 内容は「自分はこんな感じで学んでいったような気がする」という完全なる主観。
課題
- ファイル一覧を出す
ls
とよく使うオプションa
,l
,t
,1
ls
のヘルプを見るls --help
,man ls
ls
の実体がどこにあるのか調べるtype
- ファイル一覧を絞り込み
ls
,grep
- カレントディレクトリ以下のファイルを列挙
find
- カレントディレクトリにファイルがいくつあるか数える
ls
,grep
,wc -l
- カレントディレクトリのファイルを、拡張子なしで一覧化する
ls
,sed -e 's/\.[^\.]*$//g'
- カレントディレクトリの 2 つ下のディレクトリを一覧化する
find
,awk -F"/" '{ print $3 }'
,sort
,uniq
- example.com の body タグの内容を出力する
curl
,sed -n -e 'p'
- カレントディレクトリに
aaa
ディレクトリを作成するmkdir
aaa
ディレクトリにtest.txt
ファイルを作成するtouch
aaa/test.txt
にHello World!
と書き込むecho
,>>
aaa/test.txt
の中身をクリップボードにコピーするcat
,pbcopy
(Mac の場合)
- カレントディレクトリのファイル一覧と、
aaa
ディレクトリのファイル一覧の差分を見るls
,diff
,<(〜〜)
(Process Substitution)
- カレントディレクトリ以下のファイルにおいて、
Hello
という文字列がある場合はその行を、ない場合はファイルパスを表示するfind
,while read -r line; do 〜〜〜; done
,if grep
,echo
aaa
ディレクトリを削除するrm -r aaa
- 履歴を、最後から数えて 3 〜 5 行目だけ出力する
history
(,tail
),head
- 一秒ごとに現在時刻を表示する
while :; do 〜〜; done
,TZ='Asia/Tokyo' date
,sleep
シェルが行文字列志向だということが分かれば、何ができるのか大まかにわかるようになるはず。 こちらの記事がわかりやすい。
これでやりたいことのイメージがつきやすくなる(といいなぁ)。 あとはググる。
補足
正規表現を使う系のコマンドがうまくいかなかったら GNU 系のコマンドをインストールしてあげるといい。 多少挙動やオプションが違ったりするが、基本的には問題ないはず。
参考:https://kawaken.dev/posts/20200811_install-basic-gnu-commands/
この後は以下を学ぶといいかも
- PATH, 変数, 環境変数
- パイプ, エスケープ(特殊文字), 終了ステータス, サブシェル,
$()
(Command Substitution) - cut, paste, test, xargs, pushd, popd, seq, tac, rev, tee
実用的なシェル芸パーツ
実例なんでそのままは使えない可能性がある。 他のコマンドやオプションを使えば、もっときれいにできることがあるかも。
cat
- ファイルの中身に対してなんかしたいときはまずこれ
git log --oneline | awk '{ print $1 }'
git status | grep modified | sed -r -e 's/^.*: +//g'
| while read -r line; do echo "$line"; done
| sort | uniq
| while read -r line; do 〜〜〜; done
xx && yy || zz
while :; do sleep 1; done
ほか他に知っておくと便利なもの
- bash のショートカットキー(tab 補完, ctrl + a|e, ctrl + r 等)
- zsh の機能(プロンプトカスタマイズ, ブレース展開, Glob 等)
- bash, zsh のエイリアス(
alias
コマンド) - vim, less
- ファイルの中身を見るだけのときは less を使う
j
,k
,G
,F
,B
,/
,&
,Shift + F
あたり
- ファイルの中身を見るだけのときは less を使う
- よく使うコマンド(Git, docker 等)のサブコマンド・オプション・仕様
- 正規表現
- シェルスクリプトの書き方
- shebang,
set -eu
, 関数
- shebang,
- sed
- awk
参考にするとよさそうなやつ
- プログラマーの君! 騙されるな! シェルスクリプトはそう書いちゃ駄目だ!! という話
- https://stedolan.github.io/jq/
- JSON を扱うならこれがデファクト
- https://github.com/BurntSushi/ripgrep
- 再帰的 grep ならこれがおすすめ
- https://ja.wikipedia.org/wiki/UNIX哲学
- シェルスクリプトの $* と $@ の違いと雑学色々
- 標準入出力使ったら使う機会少なそう
- シェルスクリプトでlsをパイプでつなぐのはなぜ悪いのか
- 今回はシェル芸なので考慮してないけど、シェルスクリプトを書くときは気をつける
課題の答え
# ファイル一覧を出す ls ls -al ls -alt # 更新日時降順だった気がする、ログ見るときに使ってや ls -1 # シェル芸するならこれがいい # ls のヘルプを見る ## コマンドのヘルプを見るのは --help オプションや man コマンド ls --help man ls # ls の実体がどこにあるのか調べる type ls # 普段はこれがおすすめ where ls # PATH に存在するものがすべて表示される # ファイル一覧を絞り込み ls -1 | grep 'test' # カレントディレクトリ以下のファイルを列挙 find . -type f # カレントディレクトリにファイルがいくつあるか数える ## grep 部分はもっといいやり方がある気がする ls -a1 | grep -v '^\.+$' | wc -l # カレントディレクトリのファイルを、拡張子なしで一覧化する ls -1 | sed -e 's/\.[^\.]*$//g' # カレントディレクトリの 2 つ下のディレクトリを一覧化する find . -type d | awk -F"/" '{ print $3 }' | sort | uniq # example.com の body タグの内容を出力する curl https://example.com | sed -n -e '/<body>/,/<\/body>/ p' # カレントディレクトリに `aaa` ディレクトリを作成する mkdir aaa # `aaa` ディレクトリに `test.txt` ファイルを作成する touch aaa/test.txt # `aaa/test.txt` に `Hello World!` と書き込む echo "Hello World!" >>aaa/test.txt # `aaa/test.txt` の中身をクリップボードにコピーする cat aaa/test.txt | pbcopy # カレントディレクトリのファイル一覧と、`aaa` ディレクトリのファイル一覧の差分を見る diff <(ls -1) <(ls -1 aaa) # カレントディレクトリ以下のファイルにおいて、`Hello` という文字列がある場合はその行を、ない場合はファイルパスを表示する find . -type f | while read -r line; do grep -q Hello "$line" && grep Hello "$line" || echo "$line"; done ## 読みやすいのはこっちかも find . -type f | while read -r line; do if grep -q Hello "$line"; then grep Hello "$line"; else echo "$line"; fi; done # aaa ディレクトリを削除する rm -r aaa # 履歴を、最後から数えて 3 〜 5 行目だけ出力する history | tail -n 5 | head -n 3 # 一秒ごとに現在時刻を表示する while :; do TZ='Asia/Tokyo' date; sleep 1; done