# Doug McIlroyが示し、半世紀後の今も現役の設計思想
各プログラムは1つの仕事を完璧にこなす。grepは検索、sortは並び替え、wcは数える。
テキストを共通言語に。プログラムの出力は他のプログラムの入力になる。
完璧を求めず動くものから。捨てる勇気を持て。
巧妙さは敵。誰が読んでも分かるコードを。
# OSとあなたの間に立つ通訳
キーボードで入力したコマンドを解釈し、OSに伝える対話インタフェース。代表的なものに sh, bash, zsh, fish, PowerShell。
# 一生使う基本道具
| ls -la | ファイル一覧(隠しファイル含む) |
| cd /path | ディレクトリ移動 |
| pwd | 現在地表示 |
| mkdir -p a/b/c | 階層ディレクトリ作成 |
| rm -rf dir | 削除(再帰・強制)※破壊的 |
| cp -r src dst | コピー(再帰) |
| mv old new | 移動・リネーム |
| ln -s target name | シンボリックリンク作成 |
| cat file | 全表示 |
| less file | ページ送り表示(推奨) |
| head -n 20 | 先頭20行 |
| tail -f log | 末尾を追跡(ログ監視) |
| file x | ファイル種別判定 |
| wc -l | 行数カウント |
| grep -rn "word" . | テキスト検索(再帰・行番号) |
| find . -name "*.js" | ファイル名検索 |
| sed 's/old/new/g' f | 置換 |
| awk '{print $2}' f | 列抽出・加工 |
| sort | uniq -c | 重複カウント |
| cut -d, -f1 csv | CSVの1列目 |
| tr 'a-z' 'A-Z' | 大文字変換 |
| curl -O url | URLダウンロード |
| wget url | 同上の代替 |
| ssh user@host | リモート接続 |
| scp file user@host: | SSH経由コピー |
| rsync -avz s/ d/ | 差分同期(最強) |
| ps aux | grep x | プロセス検索 |
| top / htop | リアルタイム監視 |
| kill -9 PID | プロセス強制終了 |
| df -h | ディスク使用量 |
| du -sh dir | ディレクトリサイズ |
| chmod 755 f | パーミッション変更 |
rm -rf $VAR/ も $VARが空だと同じ事故になる。--preserve-rootはデフォルトで有効だが慢心しないこと# 小さな道具を組み合わせて巨大な仕事をする
| cmd1 | cmd2 | cmd1の出力をcmd2の入力に渡す(パイプ) |
| cmd > file | 標準出力をファイルへ(上書き) |
| cmd >> file | 追記 |
| cmd 2> err | エラー出力をファイルへ |
| cmd &> all | 両方をファイルへ |
| cmd < file | 標準入力をファイルから |
| cmd1 && cmd2 | cmd1成功時のみcmd2 |
| cmd1 || cmd2 | cmd1失敗時にcmd2 |
# アクセスログのIP上位10位 awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10 # プロジェクト全体のJSコード行数 find . -name "*.js" -not -path "*/node_modules/*" | xargs wc -l # 大きいファイル上位20 du -ah . | sort -rh | head -20 # GitHub上で公開鍵を取得して登録 curl -s https://github.com/USER.keys >> ~/.ssh/authorized_keys # 全ファイルから "TODO" を抽出して件数 grep -rn "TODO" --include="*.{js,ts,py}" . | wc -l # プロセス重い順 ps aux --sort=-%cpu | head -10
# 反復作業を自動化する芸術
#!/usr/bin/env bash set -euo pipefail # -e: エラーで即停止 # -u: 未定義変数でエラー # -o pipefail: パイプ途中の失敗もキャッチ IFS=$'\n\t' # 区切り文字を厳格に
name="世界" # 代入は = の前後にスペース禁止 echo "こんにちは、$name" echo "こんにちは、${name}さん" # 推奨形 # コマンド置換 files=$(ls *.txt) # 配列 arr=("a" "b" "c") echo "${arr[0]}" # a echo "${arr[@]}" # 全要素 echo "${#arr[@]}" # 要素数
if [[ -f "$file" ]]; then echo "ファイル存在" elif [[ -d "$file" ]]; then echo "ディレクトリ" else echo "ない" fi # テスト演算子 # -f: ファイル存在 -d: ディレクトリ -z: 空文字列 -n: 非空 # -eq -ne -lt -gt: 数値比較 ==/!=: 文字列比較
# forループ for file in *.txt; do echo "処理中: $file" done # 数値範囲 for i in {1..10}; do echo "$i" done # whileループ(ファイルを行ごと) while IFS= read -r line; do echo "行: $line" done < input.txt
greet() { local name="$1" echo "こんにちは、${name}さん" } greet "世界" # 戻り値は echo で。return は終了コード(0-255)
brew install shellcheck または shellcheck.net で即チェック$file をクオートしない → スペース入りファイル名で破滅ls *.txt | xargs cat → ls/xargsでスペース壊滅。find ... -execかfind ... -print0 | xargs -0を使えcat file | grep word → 無駄な cat。grep word fileで十分[ "$x" = "" ] → [[ -z "$x" ]] の方が頑健# Linus Torvaldsが2週間で書いた、人類の集団的記憶装置
分散型バージョン管理システム。誰がいつ何を変更したかを記録。リモート不要でローカルで完結し、ブランチで並行開発、マージで合流できる。
普段編集している実ファイル
次にコミットする内容の予告編。git addで進む
確定した履歴の倉庫。git commitで進む
| git init | 新規リポジトリ作成 |
| git clone url | リモートをコピー |
| git status | 現在の状態確認(最頻出) |
| git add file | ステージへ追加 |
| git add -p | 変更を選択的にステージ(必修) |
| git commit -m "msg" | コミット |
| git log --oneline --graph | 履歴をきれいに表示 |
| git diff | 未ステージの差分 |
| git diff --cached | ステージ済み差分 |
| git branch | ブランチ一覧 |
| git switch -c new | 新ブランチ作成・切替 |
| git merge feature | マージ |
| git rebase main | 履歴をきれいに付け替え |
| git pull | リモートから取得+マージ |
| git push | リモートに送信 |
| git stash | 未コミット変更を一時退避 |
| git restore file | 変更を取り消し |
| git restore --staged f | ステージング取り消し |
| git reset --soft HEAD~ | 直前コミットを取り消し(変更は残す) |
| git reflog | 失った履歴の救命 |
| git blame file | 誰がいつ書いたか |
| git bisect | バグ混入コミットを二分探索 |
| git cherry-pick HASH | 特定コミットを別ブランチに移植 |
main / develop / feature / release / hotfix の5本立て。大規模/リリース管理が必要なときに。
main + featureブランチのみ。シンプル、CDの強い前提。スタートアップでよく見る。
1本のmainに小さく頻繁にマージ。Google/Facebookが採用。
GitHub Flow + 環境ブランチ。staging/productionへの昇進を表現。
git merge: 履歴を保持。マージコミットができる。共有ブランチに使う。
git rebase: 履歴を直線にする。ローカルブランチで使う。公開済みの履歴をrebaseするな。
--force-with-leaseを使え。mainブランチには絶対NG。# 直前のコミットメッセージ修正 git commit --amend # 過去5コミットを整理(squash・並び替え) git rebase -i HEAD~5 # コミットを失った! git reflog git reset --hard HEAD@{2} # コミットしてはいけないファイルを履歴から消す git filter-repo --invert-paths --path secrets.txt # どのコミットでバグった? git bisect start git bisect bad HEAD git bisect good v1.0 # Gitが二分探索で犯人を特定
# 出られないと話題のエディタの脱出方法
| i | 挿入モードに入る(普通に編集できる) |
| Esc | 挿入モードを抜ける |
| :wq + Enter | 保存して終了 |
| :q! | 変更を捨てて終了 |
| h j k l | 左下上右に移動 |
| w / b | 単語の先頭へ次/前 |
| 0 / $ | 行頭/行末へ |
| gg / G | ファイル先頭/末尾へ |
| dd | 1行削除 |
| yy | 1行コピー |
| p | 貼り付け |
| u | Undo |
| /word | 検索(n で次、N で前) |
| :s/old/new/g | 現在行で置換 |
| :%s/old/new/gc | 全体置換(確認付き) |
本気でVimを使うなら vimtutor コマンドを実行するのが最短。
# 一度使うと戻れなくなる近代版
| ripgrep (rg) | grep の高速代替。.gitignore準拠 |
| fd | find の高速・簡単代替 |
| bat | cat にシンタックスハイライト |
| eza / lsd | ls のカラフル代替 |
| fzf | あらゆる選択を高速インクリメンタルで |
| jq | JSONを操作する sed/awk |
| yq | YAMLの jq |
| htop / btop | top の見やすい代替 |
| tldr | man の実例特化版 |
| zoxide (z) | cd の学習型賢い版 |
| tmux | セッション維持&分割 |
| direnv | ディレクトリ毎に環境変数 |
| mise / asdf | 言語ランタイム管理(Node/Python/Go等) |
| delta | git diff の超見やすい版 |
| lazygit | Git のTUI |
| gh | GitHub CLI |
# 履歴を全タブで共有・大量保存 export HISTSIZE=50000 export HISTFILESIZE=100000 export HISTCONTROL=ignoredups:erasedups # エイリアス alias ll='eza -la --git' alias g=git alias gs='git status' alias ..='cd ..' alias ...='cd ../..' # fzf統合(Ctrl-Rで履歴検索が劇的に進化) eval "$(fzf --bash)" # zoxide eval "$(zoxide init bash)"
$ exit 0 最強のシェル使いになるまで、毎日少しずつ