Skilore

ファイルの作成・コピー・移動・削除

ファイル操作は CLI の最も頻繁に使うスキル。安全な操作習慣を身につけ、事故を未然に防ぐことが何よりも重要である。

84 分で読めます41,541 文字

ファイルの作成・コピー・移動・削除

ファイル操作は CLI の最も頻繁に使うスキル。安全な操作習慣を身につけ、事故を未然に防ぐことが何よりも重要である。

この章で学ぶこと

  • ファイルとディレクトリの基本操作ができる
  • ワイルドカード(グロブ)を使いこなせる
  • 安全なファイル操作の習慣を身につける
  • rsync による高度なファイル同期を理解する
  • リンク(ハードリンク・シンボリックリンク)を理解する
  • ファイルの内容確認・比較ができる
  • 一括リネームやバッチ処理ができる
  • トラブルシューティングの方法を知る

前提知識

このガイドを読む前に、以下の知識があると理解が深まります:


1. ファイルの作成

1.1 touch コマンド

# ============================================
# touch — ファイル作成とタイムスタンプ更新
# ============================================
 
# 空ファイルの作成(最も基本的な使い方)
touch file.txt                  # 空ファイル作成
touch file1.txt file2.txt file3.txt  # 複数ファイルを一度に作成
touch {a,b,c}.txt               # ブレース展開で一括作成
touch file{1..10}.txt           # file1.txt 〜 file10.txt を一括作成
touch {2024..2026}-{01..12}-report.csv  # 年月パターンで作成
 
# 既存ファイルのタイムスタンプ更新
touch existing-file.txt         # 現在の日時に更新
 
# タイムスタンプの指定
touch -t 202602161030 file.txt  # 2026/02/16 10:30 に設定
touch -t 202601010000 file.txt  # 2026/01/01 00:00 に設定
touch -d "2026-02-16 10:30:00" file.txt  # 日付文字列で指定(GNU)
touch -d "yesterday" file.txt   # 昨日の日付に設定
touch -d "2 days ago" file.txt  # 2日前に設定
 
# 参照ファイルと同じタイムスタンプに設定
touch -r reference.txt target.txt  # reference.txt と同じ日時にする
 
# 特定のタイムスタンプのみ変更
touch -a file.txt               # atime(アクセス日時)のみ更新
touch -m file.txt               # mtime(更新日時)のみ更新
 
# ファイルが存在しない場合は作成しない
touch -c nonexistent.txt        # ファイルが無ければ何もしない
 
# 実務的な活用
# 1. ロックファイルの作成
touch /tmp/myapp.lock
 
# 2. 設定ファイルのテンプレート作成
touch .env .env.example .gitignore README.md
 
# 3. ビルドシステムのタイムスタンプ操作
touch -r src/main.c build/output  # ソースと同じ日時にする

1.2 テキストファイルの作成

# ============================================
# テキストファイルの作成方法
# ============================================
 
# echo コマンド
echo "Hello, World!" > file.txt         # 上書き作成(>)
echo "Additional line" >> file.txt      # 追記(>>)
echo -e "Line 1\nLine 2\nLine 3" > file.txt  # 改行を含む
 
# printf コマンド(echo より制御しやすい)
printf "Name: %s\nAge: %d\n" "Taro" 30 > profile.txt
printf "%s\n" "line1" "line2" "line3" > file.txt
 
# cat とヒアドキュメント
cat > config.txt << 'EOF'
# 設定ファイル
database_host=localhost
database_port=5432
database_name=myapp
EOF
 
# ヒアドキュメント(変数展開あり)
DB_HOST="localhost"
cat > config.txt << EOF
database_host=${DB_HOST}
database_port=5432
EOF
 
# ヒアドキュメント(変数展開なし — シングルクォートで囲む)
cat > script.sh << 'SCRIPT'
#!/bin/bash
echo "Hello, $USER!"
echo "Today is $(date)"
SCRIPT
 
# tee コマンド(標準出力とファイルの両方に書き込み)
echo "Hello" | tee file.txt              # 画面にも表示してファイルにも書き込み
echo "World" | tee -a file.txt           # 追記モード
echo "secret" | sudo tee /etc/config     # sudo でのファイル書き込み
 
# /dev/null への書き込み(出力を捨てる)
command > /dev/null 2>&1                  # 標準出力と標準エラーを破棄

1.3 ディレクトリの作成

# ============================================
# mkdir — ディレクトリ作成
# ============================================
 
# 基本操作
mkdir dirname                   # ディレクトリ作成
mkdir dir1 dir2 dir3            # 複数ディレクトリを一度に作成
 
# ネストしたディレクトリを一気に作成(-p: parents)
mkdir -p path/to/nested/dir     # 中間ディレクトリも自動作成
mkdir -p project/{src,tests,docs,config}  # プロジェクト構造を一括作成
mkdir -p project/src/{components,pages,utils,styles}  # ネストした構造
 
# パーミッションを指定して作成
mkdir -m 700 secret_dir         # rwx------
mkdir -m 755 public_dir         # rwxr-xr-x
 
# 詳細表示
mkdir -v dirname                # 作成したことを表示
mkdir -pv path/to/nested        # 中間ディレクトリの作成も表示
 
# プロジェクト構造の一括作成
mkdir -p myproject/{src/{main,test}/{java,resources},docs,config,scripts,build}
 
# 日付ベースのディレクトリ作成
mkdir -p "backup/$(date +%Y/%m/%d)"  # backup/2026/02/16
 
# テンポラリディレクトリの作成
mktemp -d                       # /tmp/tmp.XXXXXXXXXX を作成
mktemp -d /tmp/myapp-XXXXXX     # パターン指定
TMPDIR=$(mktemp -d)             # 変数に格納して使う
# 使い終わったら削除
rm -rf "$TMPDIR"

2. ファイルのコピー

2.1 cp コマンド

# ============================================
# cp — ファイル・ディレクトリのコピー
# ============================================
 
# 基本操作
cp source.txt dest.txt          # ファイルコピー
cp source.txt /path/to/dir/     # ディレクトリにコピー(同名)
cp source.txt /path/to/dir/new_name.txt  # 新しい名前でコピー
 
# ディレクトリのコピー
cp -r source_dir/ dest_dir/     # 再帰的にコピー(-r: recursive)
cp -R source_dir/ dest_dir/     # -r と同じ(大文字R)
 
# 重要なオプション
cp -i source.txt dest.txt       # 上書き前に確認(interactive)
cp -n source.txt dest.txt       # 上書きしない(no-clobber)
cp -f source.txt dest.txt       # 強制上書き(force)
cp -v source.txt dest.txt       # 操作内容を表示(verbose)
 
# メタデータの保持
cp -p source.txt dest.txt       # パーミッション・タイムスタンプを保持
cp -a source/ dest/             # アーカイブモード(-dR --preserve=all と同等)
                                 # パーミッション、所有者、タイムスタンプ、
                                 # シンボリックリンク、拡張属性を全て保持
 
# バックアップ付きコピー(GNU拡張)
cp --backup=numbered file.txt dest/     # file.txt.~1~, file.txt.~2~ ...
cp --backup=simple file.txt dest/       # file.txt~ (チルダ付き)
cp -b file.txt dest/                    # デフォルトのバックアップ
 
# 更新されたファイルのみコピー
cp -u source.txt dest.txt       # dest が古い場合のみコピー
 
# スパースファイルの効率的なコピー
cp --sparse=auto large-file dest/  # スパース領域を保持
 
# 複数ファイルのコピー
cp file1.txt file2.txt file3.txt /dest/dir/
cp *.txt /dest/dir/             # ワイルドカードで一括コピー
cp -t /dest/dir/ file1 file2    # -t でターゲットを先に指定
 
# シンボリックリンクの扱い
cp -L symlink.txt dest/         # リンク先の実体をコピー(デフォルト)
cp -d symlink.txt dest/         # シンボリックリンクとしてコピー
cp -P symlink.txt dest/         # -d と同じ(POSIX)
 
# 進捗表示付きコピー(大きなファイル)
# cp 自体に進捗表示機能はないため、代替手段を使う
pv source.iso > dest.iso         # pv (pipe viewer) を使う
rsync -avh --progress source dest  # rsync の進捗表示
 
# 実践的な使い方
cp -av /etc/nginx/ /backup/nginx-$(date +%Y%m%d)/  # 日付付きバックアップ
cp -rp /home/user/project/ /backup/project/          # プロジェクトの完全バックアップ

2.2 cp の注意点

# ============================================
# cp の注意すべきポイント
# ============================================
 
# 注意1: ディレクトリコピーのトレイリングスラッシュ
# 結果が異なる場合がある
cp -r source dest              # source → dest/source にコピーされる場合がある
cp -r source/ dest/            # source の中身を dest にコピー
 
# 注意2: シンボリックリンクの扱い
# デフォルトではリンク先の実体がコピーされる
cp symlink.txt copy.txt        # リンク先のファイルがコピーされる
cp -d symlink.txt copy.txt     # シンボリックリンクとしてコピーされる
 
# 注意3: 特殊ファイルのコピー
# /dev, /proc 配下のファイルは通常の cp ではコピーできない
 
# 注意4: SELinux / ACL の扱い
cp --preserve=all source dest  # SELinux コンテキスト、ACL も保持
 
# 注意5: クロスファイルシステムのコピー
# 異なるファイルシステム間でのコピーではinode番号が変わる
# ハードリンクの関係は保持されない
 
# 安全なコピーの習慣
# 1. 常に -i をつける(エイリアスとして設定推奨)
alias cp='cp -i'
 
# 2. 大量コピー前にドライランを行う(rsync -n)
rsync -avhn source/ dest/      # -n でドライラン
 
# 3. 重要なファイルはバックアップ付きでコピー
cp --backup=numbered important.conf /etc/

3. ファイルの移動・リネーム

3.1 mv コマンド

# ============================================
# mv — ファイルの移動・リネーム
# ============================================
 
# リネーム
mv old_name.txt new_name.txt    # ファイルのリネーム
mv old_dir/ new_dir/            # ディレクトリのリネーム
 
# 移動
mv file.txt /path/to/dir/      # ファイルを移動
mv file.txt /path/to/dir/new_name.txt  # 移動 + リネーム
mv dir1/ /path/to/dir2/        # ディレクトリを移動
 
# 重要なオプション
mv -i source dest               # 上書き前に確認(interactive)
mv -n source dest               # 上書きしない(no-clobber)
mv -f source dest               # 強制移動(force)
mv -v source dest               # 操作内容を表示(verbose)
 
# バックアップ付き移動(GNU拡張)
mv --backup=numbered file.txt dest/
mv -b file.txt dest/            # デフォルトのバックアップ
 
# 更新されたファイルのみ移動
mv -u source.txt dest.txt       # dest が古い場合のみ移動
 
# 複数ファイルの移動
mv file1.txt file2.txt file3.txt /dest/dir/
mv *.log /var/log/archive/      # ログファイルを一括移動
mv -t /dest/dir/ file1 file2    # -t でターゲットを先に指定
 
# mv の特性
# - 同一ファイルシステム内では瞬時(inode のリネームのみ)
# - 異なるファイルシステム間ではコピー+削除(時間がかかる)
 
# 安全な mv の習慣
alias mv='mv -i'               # 上書き確認をデフォルトに

3.2 一括リネーム

# ============================================
# 一括リネームのテクニック
# ============================================
 
# rename コマンド(Perl版)
# Ubuntu/Debian: apt install rename
# macOS: brew install rename
 
# 基本的な使い方(Perl正規表現)
rename 's/\.txt$/\.md/' *.txt                 # .txt → .md
rename 's/old/new/' *.txt                     # ファイル名の old → new
rename 'y/A-Z/a-z/' *.JPG                    # 大文字 → 小文字
rename 's/^/prefix_/' *.txt                   # プレフィックス追加
rename 's/$/.bak/' *.conf                     # サフィックス追加
rename 's/\s/_/g' *                           # スペース → アンダースコア
rename 's/[^a-zA-Z0-9._-]/_/g' *             # 特殊文字を置換
 
# ドライラン(実行前の確認)
rename -n 's/\.txt$/\.md/' *.txt              # -n で実行せずに結果を表示
 
# mmv コマンド(マスムーブ)
# brew install mmv
mmv "*.txt" "#1.md"                           # .txt → .md
mmv "*.JPG" "#1.jpg"                          # .JPG → .jpg
mmv "chapter*" "ch*"                          # chapter → ch
 
# bash のループによるリネーム
for f in *.txt; do
    mv "$f" "${f%.txt}.md"                    # .txt → .md
done
 
for f in *.JPG; do
    mv "$f" "${f,,}"                          # 大文字 → 小文字(bash 4+)
done
 
# 連番リネーム
i=1
for f in *.jpg; do
    mv "$f" "photo_$(printf '%03d' $i).jpg"   # photo_001.jpg, photo_002.jpg, ...
    ((i++))
done
 
# zsh のzmv(zsh限定、強力なリネームツール)
autoload -Uz zmv
 
zmv '(*).txt' '$1.md'                         # .txt → .md
zmv '(*).JPG' '${1:l}.jpg'                   # 大文字 → 小文字 + .JPG → .jpg
zmv '(*)_(*)' '$2_$1'                         # パーツの入れ替え
zmv -n '(*).txt' '$1.md'                      # ドライラン
 
# 日付をファイル名に追加
for f in *.log; do
    date=$(stat -f "%Sm" -t "%Y%m%d" "$f" 2>/dev/null || stat -c "%y" "$f" 2>/dev/null | cut -d' ' -f1 | tr -d '-')
    mv "$f" "${date}_${f}"
done

4. ファイルの削除

4.1 rm コマンド

# ============================================
# rm — ファイル・ディレクトリの削除
# ============================================
 
# 基本操作
rm file.txt                     # ファイル削除
rm file1.txt file2.txt file3.txt  # 複数ファイル削除
 
# ディレクトリの削除
rm -r directory/                # ディレクトリを再帰的に削除
rm -rf directory/               # 確認なしで強制削除
rmdir empty_dir                 # 空ディレクトリのみ削除(安全)
 
# 重要なオプション
rm -i file.txt                  # 削除前に確認(interactive)
rm -I *.txt                     # 3個以上 or 再帰削除時に1回確認(GNU)
rm -v file.txt                  # 削除内容を表示(verbose)
rm -d empty_dir                 # 空ディレクトリの削除(rmdir相当)
 
# ワイルドカードでの削除
rm *.tmp                        # .tmp ファイルを全削除
rm *.log                        # .log ファイルを全削除
rm -r __pycache__/              # Python キャッシュ削除
 
# 特殊なファイル名の削除
rm -- -filename.txt             # ハイフンで始まるファイル(-- でオプション終了)
rm ./-filename.txt              # パス指定でも可能
rm $'\x00file'                  # NULL文字を含むファイル名
 
# ============================================
# 危険なコマンド(絶対に注意!)
# ============================================
# rm -rf /                ← システム全体を削除(最悪のコマンド)
# rm -rf /*               ← 同上
# rm -rf ~                ← ホームディレクトリ全削除
# rm -rf *                ← カレントディレクトリの全ファイル削除
# rm -rf .                ← 一部のシステムで動作する(危険)
# rm -rf "$UNDEFINED"/*   ← 変数が未定義だと rm -rf /* になる!
 
# ============================================
# 安全対策
# ============================================
 
# 1. エイリアスで確認付きにする
alias rm='rm -i'
 
# 2. rm の代わりに trash を使う
# brew install trash-cli    # macOS
# sudo apt install trash-cli  # Ubuntu
trash file.txt                  # ゴミ箱に移動(復元可能)
trash-list                      # ゴミ箱の内容一覧
trash-restore                   # ゴミ箱から復元
trash-empty                     # ゴミ箱を空にする
 
# 3. 削除前に確認する習慣
ls *.tmp                        # まず対象を確認
rm *.tmp                        # 確認後に削除
 
# 4. 変数を使う前にチェック
if [ -n "$DIR" ]; then
    rm -rf "$DIR"
fi
 
# 5. --preserve-root(GNU rm のデフォルト)
rm -rf --preserve-root /        # / の削除を拒否(デフォルトで有効)
rm -rf --no-preserve-root /     # 保護を無効化(絶対に使わない)
 
# 6. safe-rm をインストール
# 重要なディレクトリの削除を防ぐラッパー
# apt install safe-rm

4.2 find を使った条件付き削除

# ============================================
# find + rm で条件に基づく削除
# ============================================
 
# 古いファイルの削除
find /var/log -name "*.log" -mtime +30 -delete           # 30日以上前のログ
find /tmp -mtime +7 -delete                               # 7日以上前のtmpファイル
find . -name "*.bak" -mtime +90 -delete                   # 90日以上前のバックアップ
 
# サイズベースの削除
find . -type f -size +100M -delete                        # 100MB以上のファイル
find . -type f -size 0 -delete                            # 空ファイル
 
# 特定パターンの削除
find . -name "*.pyc" -delete                              # Python コンパイル済みファイル
find . -name "__pycache__" -type d -exec rm -rf {} +      # Python キャッシュ
find . -name ".DS_Store" -delete                          # macOS のメタデータ
find . -name "Thumbs.db" -delete                          # Windows のサムネイル
find . -name "*.swp" -delete                              # Vim のスワップファイル
find . -name "*~" -delete                                 # バックアップファイル
find . -name "node_modules" -type d -prune -exec rm -rf {} +  # node_modules
 
# 安全な削除(-exec で確認)
find . -name "*.tmp" -exec rm -i {} \;                    # 1つずつ確認
find . -name "*.tmp" -ok rm {} \;                         # -ok は常に確認
 
# ドライラン(削除対象の確認のみ)
find . -name "*.tmp" -print                               # 対象ファイルを表示
find . -name "*.tmp" -ls                                  # 詳細情報付きで表示
find /tmp -mtime +7 -ls                                   # 古いファイルの確認
 
# 確認後に削除するワークフロー
find . -name "*.tmp" -print > /tmp/delete_list.txt        # リストを作成
cat /tmp/delete_list.txt                                   # 内容を確認
xargs rm -v < /tmp/delete_list.txt                        # 確認後に削除

5. ワイルドカード(グロブ)

5.1 基本的なワイルドカード

# ============================================
# ワイルドカードパターンの完全ガイド
# ============================================
 
# 基本パターン
*              # 任意の文字列(0文字以上)
?              # 任意の1文字
[abc]          # a, b, c のいずれか1文字
[a-z]          # a〜z の範囲の1文字
[A-Z]          # A〜Z の範囲の1文字
[0-9]          # 0〜9 の範囲の1文字
[!abc]         # a, b, c 以外の1文字(否定)
[^abc]         # 同上(一部のシェルで)
{foo,bar}      # foo または bar(ブレース展開 — グロブではなくシェルの機能)
 
# 使用例
ls *.md                         # 全 .md ファイル
ls *.{js,ts}                    # .js と .ts ファイル
ls image?.png                   # image1.png, image2.png 等
ls file[1-3].txt                # file1.txt, file2.txt, file3.txt
ls file[!0-9].txt               # file の後に数字以外が来るファイル
ls [A-Z]*.txt                   # 大文字で始まる .txt ファイル
ls data_202[0-6]*.csv           # data_2020 〜 data_2026 のCSV
 
# ブレース展開の活用
cp {main,test}.py /tmp/         # main.py と test.py をコピー
mkdir -p project/{src,tests,docs}  # 3ディレクトリ一括作成
mv file.{txt,bak}              # file.txt → file.bak にリネーム
echo {1..10}                    # 1 2 3 4 5 6 7 8 9 10
echo {01..10}                   # 01 02 03 04 05 06 07 08 09 10
echo {a..z}                     # a b c ... z
echo file{A,B,C}_{1..3}.txt    # fileA_1.txt fileA_2.txt ... fileC_3.txt
 
# ブレース展開とグロブの組み合わせ
ls src/**/*.{js,ts,jsx,tsx}     # src 以下の全JS/TSファイル
cp config/*.{yml,yaml,json} /backup/  # 設定ファイルをバックアップ

5.2 高度なグロブパターン

# ============================================
# 拡張グロブ(Extended Globbing)
# ============================================
 
# bash の拡張グロブを有効にする
shopt -s extglob
 
# パターン
*(pattern)     # 0回以上の繰り返し
+(pattern)     # 1回以上の繰り返し
?(pattern)     # 0回または1回
@(pattern)     # ちょうど1回
!(pattern)     # パターン以外
 
# 使用例
ls !(*.txt)                     # .txt 以外のファイル
ls !(*.bak|*.tmp)               # .bak と .tmp 以外
rm !(important.txt)             # important.txt 以外を削除
cp !(node_modules)/* /backup/   # node_modules 以外をコピー
ls @(*.jpg|*.png|*.gif)         # 画像ファイルのみ
 
# ============================================
# zsh のグロブ修飾子(Glob Qualifiers)
# ============================================
 
# zsh は標準で強力なグロブ機能を持つ
ls *.txt(.)                     # 通常のファイルのみ
ls *(/)                         # ディレクトリのみ
ls *(@)                         # シンボリックリンクのみ
ls *(*)                         # 実行可能ファイルのみ
ls *(m-7)                       # 7日以内に更新されたファイル
ls *(m+30)                      # 30日以上前に更新されたファイル
ls *(Lk+100)                    # 100KB以上のファイル
ls *(Lm+10)                     # 10MB以上のファイル
ls *(om)                        # 更新日時順(新しい順)
ls *(Om)                        # 更新日時順(古い順)
ls *(oL)                        # サイズ順(小さい順)
ls *(OL)                        # サイズ順(大きい順)
ls *(.om[1,5])                  # 最近更新されたファイルのトップ5
ls *(u:root:)                   # root が所有者のファイル
 
# 再帰グロブ(**)
ls **/*.md                      # サブディレクトリ含む全 .md ファイル
ls **/*.{js,ts}                 # サブディレクトリ含む全 JS/TS ファイル
 
# bash の再帰グロブを有効にする
shopt -s globstar               # bash 4+ で ** を有効化
ls **/*.md                      # zsh と同様に動作
 
# NULL グロブ(マッチしない場合にエラーにしない)
setopt NULL_GLOB                # zsh: マッチなしの場合は空に展開
shopt -s nullglob               # bash: マッチなしの場合は空に展開
 
# ドットファイルもグロブに含める
setopt GLOB_DOTS                # zsh: .* もマッチ
shopt -s dotglob                # bash: .* もマッチ

6. rsync による高度なファイル同期

6.1 rsync の基本

# ============================================
# rsync — 高機能なファイル同期ツール
# ============================================
 
# インストール(通常プリインストール済み)
brew install rsync              # macOS(最新版)
sudo apt install rsync          # Ubuntu/Debian
 
# 基本的な使い方
rsync -avh source/ dest/        # ローカル同期
# -a: アーカイブモード(-rlptgoD と同等)
#     -r: 再帰的
#     -l: シンボリックリンクを保持
#     -p: パーミッションを保持
#     -t: タイムスタンプを保持
#     -g: グループを保持
#     -o: オーナーを保持
#     -D: デバイスファイルとスペシャルファイルを保持
# -v: 詳細表示
# -h: 人間可読なサイズ表示
 
# トレイリングスラッシュの重要性
rsync -avh source/ dest/        # source の中身を dest にコピー
rsync -avh source dest/         # source ディレクトリ自体を dest にコピー
# → rsync -avh source dest/ は dest/source/ を作成する
 
# ドライラン(実行前の確認)
rsync -avhn source/ dest/       # -n でドライラン(実行しない)
rsync -avh --dry-run source/ dest/  # 同上
 
# 進捗表示
rsync -avh --progress source/ dest/           # ファイルごとの進捗
rsync -avh --info=progress2 source/ dest/     # 全体の進捗(%表示)
 
# 削除オプション(ソースに無いファイルをdestから削除)
rsync -avh --delete source/ dest/             # destの余分なファイルを削除
rsync -avh --delete-before source/ dest/      # 転送前に削除
rsync -avh --delete-after source/ dest/       # 転送後に削除
rsync -avh --delete-excluded source/ dest/    # 除外されたファイルも削除

6.2 rsync の除外パターン

# ============================================
# rsync の除外/包含パターン
# ============================================
 
# 除外パターン
rsync -avh --exclude='*.log' source/ dest/
rsync -avh --exclude='node_modules' source/ dest/
rsync -avh --exclude='.git' --exclude='*.tmp' source/ dest/
rsync -avh --exclude='*.{log,tmp,bak}' source/ dest/
 
# 除外ファイルからの読み込み
rsync -avh --exclude-from='exclude-list.txt' source/ dest/
 
# exclude-list.txt の内容例:
# node_modules
# .git
# *.log
# *.tmp
# __pycache__
# .DS_Store
# dist/
# build/
 
# 包含パターン(除外の中から特定のものだけ含める)
rsync -avh --include='*.py' --exclude='*' source/ dest/  # .py ファイルのみ
rsync -avh --include='*/' --include='*.py' --exclude='*' source/ dest/  # ディレクトリ構造を保持
 
# フィルタールール
rsync -avh --filter='- *.log' --filter='- node_modules/' source/ dest/
rsync -avh -f '- *.log' -f '- .git/' source/ dest/

6.3 rsync のリモート同期

# ============================================
# rsync のリモート同期(SSH経由)
# ============================================
 
# ローカル → リモート
rsync -avh source/ user@host:/path/to/dest/
rsync -avh -e "ssh -p 2222" source/ user@host:/path/to/dest/  # ポート指定
 
# リモート → ローカル
rsync -avh user@host:/path/to/source/ dest/
 
# 帯域制限
rsync -avh --bwlimit=1000 source/ user@host:dest/  # 1000 KB/s に制限
 
# 圧縮転送
rsync -avhz source/ user@host:dest/                 # -z で圧縮
 
# 部分転送の再開(大きなファイルの転送時)
rsync -avh --partial source/ dest/                   # 中断したファイルを保持
rsync -avhP source/ dest/                            # -P = --partial --progress
 
# SSH鍵を指定
rsync -avh -e "ssh -i ~/.ssh/specific_key" source/ user@host:dest/
 
# ============================================
# 実践的な rsync 使用例
# ============================================
 
# プロジェクトのバックアップ
rsync -avh --delete \
    --exclude='node_modules' \
    --exclude='.git' \
    --exclude='dist' \
    --exclude='*.log' \
    ~/projects/ /backup/projects/
 
# ウェブサーバーへのデプロイ
rsync -avhz --delete \
    --exclude='.env' \
    --exclude='.git' \
    dist/ user@server:/var/www/html/
 
# 設定ファイルの同期
rsync -avh \
    ~/.zshrc ~/.gitconfig ~/.vimrc \
    user@newmachine:~/
 
# 増分バックアップ(ハードリンクベース)
rsync -avh --delete \
    --link-dest=/backup/latest \
    source/ /backup/$(date +%Y%m%d)/
ln -sfn /backup/$(date +%Y%m%d) /backup/latest

7. リンク(ハードリンクとシンボリックリンク)

7.1 リンクの基本

# ============================================
# ハードリンクとシンボリックリンク
# ============================================
 
# ハードリンク(同じinode を指す別の名前)
ln original.txt hardlink.txt
# - 同じinode番号を持つ
# - 元ファイルを削除してもリンクからアクセス可能
# - 同じファイルシステム内のみ
# - ディレクトリには作成不可
 
# シンボリックリンク(ショートカット)
ln -s /path/to/original symlink
ln -s /path/to/dir dir_link
# - 別のinode番号を持つ
# - 元ファイルを削除するとリンク切れ(dangling link)
# - 異なるファイルシステムでもOK
# - ディレクトリにも作成可能
 
# リンクの確認
ls -la symlink                  # l で始まる = シンボリックリンク
ls -li file hardlink            # 同じinode番号 = ハードリンク
readlink symlink                # リンク先を表示
readlink -f symlink             # リンク先の絶対パス
stat file                       # inode情報の詳細
 
# リンクの更新
ln -sf /new/target symlink      # -f で既存リンクを上書き
ln -sfn /new/target dir_link    # -n でディレクトリリンクを上書き
 
# リンクの削除
rm symlink                      # シンボリックリンクの削除
unlink symlink                  # 同上(より明示的)
# 注意: rm symlink/  のように末尾にスラッシュを付けると
#        リンク先のディレクトリの中身が削除される可能性がある
 
# 壊れたシンボリックリンクの検出
find . -type l ! -exec test -e {} \; -print  # 壊れたリンクを検出
find . -xtype l                              # 壊れたリンクを検出(GNU find)
 
# 実践的な使用例
# 1. バージョン切り替え
ln -sf /opt/python-3.11/bin/python3 /usr/local/bin/python3
ln -sf /opt/node-20/bin/node /usr/local/bin/node
 
# 2. 設定ファイルの管理(dotfiles)
ln -sf ~/.dotfiles/zsh/.zshrc ~/.zshrc
ln -sf ~/.dotfiles/git/.gitconfig ~/.gitconfig
 
# 3. ログローテーション
ln -sf /var/log/app/app-$(date +%Y%m%d).log /var/log/app/current.log
 
# 4. ライブラリのバージョン管理
ln -sf libfoo.so.1.2.3 libfoo.so.1
ln -sf libfoo.so.1 libfoo.so

8. ファイルの内容確認

8.1 ファイル閲覧コマンド

# ============================================
# ファイル内容の確認方法
# ============================================
 
# cat — ファイル全体を表示
cat file.txt                    # ファイル内容を表示
cat -n file.txt                 # 行番号付き
cat -b file.txt                 # 空行以外に行番号
cat -s file.txt                 # 連続する空行を1行に
cat -A file.txt                 # 制御文字と行末を表示
cat file1.txt file2.txt         # 複数ファイルを連結表示
 
# less — ページャ(最もよく使う)
less file.txt                   # ページャで表示
less -N file.txt                # 行番号付き
less +G file.txt                # ファイル末尾から表示
less +/pattern file.txt         # パターンを検索して表示
# less 内の操作: j/k(上下), /検索, n(次), q(終了)
 
# head — ファイルの先頭を表示
head file.txt                   # 最初の10行(デフォルト)
head -n 20 file.txt             # 最初の20行
head -n -5 file.txt             # 最後の5行を除いた全行
head -c 100 file.txt            # 最初の100バイト
head -1 *.csv                   # 各CSVファイルの1行目(ヘッダー確認)
 
# tail — ファイルの末尾を表示
tail file.txt                   # 最後の10行(デフォルト)
tail -n 20 file.txt             # 最後の20行
tail -n +5 file.txt             # 5行目から最後まで
tail -f file.txt                # リアルタイム監視(ログ監視に最適)
tail -F file.txt                # ファイルのローテーションに追従
tail -f /var/log/syslog         # ログのリアルタイム監視
 
# wc — ファイルの統計
wc file.txt                     # 行数 単語数 バイト数
wc -l file.txt                  # 行数のみ
wc -w file.txt                  # 単語数のみ
wc -c file.txt                  # バイト数のみ
wc -m file.txt                  # 文字数のみ
wc -l *.py                      # 各ファイルの行数
 
# file — ファイルの種類を判定
file document.pdf               # PDF document
file image.jpg                  # JPEG image data
file script.sh                  # Bourne-Again shell script
file binary                     # ELF 64-bit LSB executable
file -i file.txt                # MIME タイプを表示
 
# stat — ファイルの詳細情報
stat file.txt                   # inode、サイズ、タイムスタンプ等の詳細
 
# bat — cat の改良版(シンタックスハイライト付き)
# brew install bat
bat file.py                     # シンタックスハイライト付き表示
bat -n file.py                  # 行番号のみ(ヘッダーなし)
bat --plain file.py             # プレーン表示
bat -l python file              # 言語指定
bat --diff file.py              # Git差分のハイライト

8.2 ファイルの比較

# ============================================
# ファイルの比較
# ============================================
 
# diff — ファイルの差分表示
diff file1.txt file2.txt        # 差分を表示
diff -u file1.txt file2.txt     # unified 形式(最もよく使う)
diff -y file1.txt file2.txt     # 左右並列表示
diff -w file1.txt file2.txt     # 空白の違いを無視
diff -i file1.txt file2.txt     # 大文字小文字を無視
diff -r dir1/ dir2/             # ディレクトリの再帰的比較
diff -rq dir1/ dir2/            # 差異のあるファイル名のみ表示
diff --color file1.txt file2.txt  # カラー表示
 
# colordiff(diff のカラー版)
# brew install colordiff
colordiff file1.txt file2.txt
 
# delta(Git diff の改良版)
diff -u file1.txt file2.txt | delta
 
# comm — ソート済みファイルの比較
sort file1.txt > sorted1.txt
sort file2.txt > sorted2.txt
comm sorted1.txt sorted2.txt
# 出力: 3カラム(file1のみ, file2のみ, 共通)
comm -12 sorted1.txt sorted2.txt  # 共通行のみ
comm -23 sorted1.txt sorted2.txt  # file1にのみ存在する行
comm -13 sorted1.txt sorted2.txt  # file2にのみ存在する行
 
# cmp — バイナリファイルの比較
cmp file1 file2                 # 最初に異なるバイト位置を表示
cmp -l file1 file2             # 全ての異なるバイトを表示
 
# md5sum/sha256sum — ファイルのハッシュ比較
md5sum file1.txt file2.txt      # MD5ハッシュ
sha256sum file1.txt file2.txt   # SHA-256ハッシュ
md5 file1.txt file2.txt         # macOS
 
# vimdiff — Vimでの並列比較
vimdiff file1.txt file2.txt     # Vimのdiffモード

9. 実践演習

演習1: [基礎] ── ファイル操作の基本

# 課題: 以下の操作を実行してください
 
# 1. 作業ディレクトリを作成
mkdir -p /tmp/file-exercise && cd /tmp/file-exercise
 
# 2. テストファイルを作成
touch file{1..5}.txt
echo "Hello World" > hello.txt
cat > config.ini << 'EOF'
[database]
host=localhost
port=5432
EOF
 
# 3. ファイルの確認
ls -la
cat config.ini
wc -l *.txt
 
# 4. コピーと移動
cp hello.txt hello_backup.txt
mv file5.txt renamed.txt
mkdir -p backup && cp *.txt backup/
 
# 5. 削除
rm file3.txt
rm -r backup/
 
# 6. クリーンアップ
cd ~ && rm -rf /tmp/file-exercise

演習2: [中級] ── ワイルドカードとバッチ操作

# 課題: ワイルドカードを使って効率的にファイルを操作する
 
# 1. テスト環境の作成
mkdir -p /tmp/glob-exercise && cd /tmp/glob-exercise
touch report_{2024,2025,2026}_{Q1,Q2,Q3,Q4}.csv
touch image_{001..020}.jpg
touch document_{draft,final,review}.docx
mkdir -p archive
 
# 2. グロブパターンで操作
ls report_2025_*.csv             # 2025年のレポートのみ
ls image_{001..010}.jpg          # 最初の10枚
cp report_2024_*.csv archive/    # 2024年をアーカイブ
mv *.docx archive/               # 全ドキュメントをアーカイブ
 
# 3. ブレース展開の活用
mkdir -p project/{src/{main,test},docs,config}
touch project/src/main/{app,utils,config}.py
touch project/src/test/test_{app,utils,config}.py
 
# 4. tree で構造確認
tree project/
 
# クリーンアップ
cd ~ && rm -rf /tmp/glob-exercise

演習3: [中級] ── rsync でバックアップ

# 課題: rsync を使ったバックアップスクリプトを作成する
 
#!/bin/bash
# backup.sh — rsync バックアップスクリプト
 
set -euo pipefail
 
SOURCE="$HOME/projects/"
DEST="/backup/projects/"
EXCLUDE_FILE="/tmp/rsync-exclude.txt"
 
# 除外ファイルの作成
cat > "$EXCLUDE_FILE" << 'EOF'
node_modules
.git
dist
build
*.log
*.tmp
__pycache__
.DS_Store
EOF
 
# ドライラン
echo "=== Dry Run ==="
rsync -avhn --delete --exclude-from="$EXCLUDE_FILE" "$SOURCE" "$DEST"
 
# 確認
read -p "Proceed with backup? [y/N] " answer
if [[ "$answer" =~ ^[Yy]$ ]]; then
    echo "=== Executing Backup ==="
    rsync -avh --delete --exclude-from="$EXCLUDE_FILE" --info=progress2 "$SOURCE" "$DEST"
    echo "Backup complete!"
else
    echo "Backup cancelled."
fi
 
rm -f "$EXCLUDE_FILE"

演習4: [上級] ── 一括リネームスクリプト

# 課題: 柔軟な一括リネームスクリプトを作成する
 
#!/bin/bash
# batch-rename.sh — 一括リネームスクリプト
 
set -euo pipefail
 
usage() {
    cat << EOF
Usage: $(basename "$0") [OPTIONS] PATTERN REPLACEMENT [DIRECTORY]
 
ファイル名の一括リネームを行います。
 
Options:
  -n, --dry-run    ドライラン(リネームを実行しない)
  -r, --recursive  再帰的にリネーム
  -i, --ignore-case 大文字小文字を無視
  -v, --verbose    詳細表示
  -h, --help       ヘルプ表示
 
Examples:
  $(basename "$0") .txt .md                     # .txt → .md
  $(basename "$0") -n "old" "new"               # ドライラン
  $(basename "$0") -r "draft_" "" ~/documents   # プレフィックス削除
EOF
}
 
DRY_RUN=false
RECURSIVE=false
VERBOSE=false
IGNORE_CASE=""
 
while [[ $# -gt 0 ]]; do
    case "$1" in
        -n|--dry-run)    DRY_RUN=true; shift ;;
        -r|--recursive)  RECURSIVE=true; shift ;;
        -i|--ignore-case) IGNORE_CASE="I"; shift ;;
        -v|--verbose)    VERBOSE=true; shift ;;
        -h|--help)       usage; exit 0 ;;
        -*)              echo "Unknown option: $1" >&2; exit 1 ;;
        *)               break ;;
    esac
done
 
if [[ $# -lt 2 ]]; then
    usage >&2
    exit 1
fi
 
PATTERN="$1"
REPLACEMENT="$2"
DIRECTORY="${3:-.}"
 
count=0
find_opts=(-name "*${PATTERN}*")
if [[ "$RECURSIVE" == false ]]; then
    find_opts+=(-maxdepth 1)
fi
 
while IFS= read -r -d '' file; do
    dir=$(dirname "$file")
    base=$(basename "$file")
    newname="${base//${PATTERN}/${REPLACEMENT}}"
 
    if [[ "$base" != "$newname" ]]; then
        ((count++))
        if [[ "$DRY_RUN" == true ]]; then
            echo "[DRY RUN] $file$dir/$newname"
        else
            mv -v "$file" "$dir/$newname"
        fi
    fi
done < <(find "$DIRECTORY" "${find_opts[@]}" -print0)
 
echo "Total: $count file(s) processed"

演習5: [上級] ── プロジェクトクリーナー

# 課題: 開発プロジェクトの不要ファイルを安全にクリーンアップするスクリプト
 
#!/bin/bash
# project-cleaner.sh — プロジェクトクリーナー
 
set -euo pipefail
 
TARGET="${1:-.}"
DRY_RUN=false
[[ "${2:-}" == "-n" ]] && DRY_RUN=true
 
echo "=== Project Cleaner ==="
echo "Target: $(realpath "$TARGET")"
[[ "$DRY_RUN" == true ]] && echo "Mode: DRY RUN"
 
# クリーンアップ対象の定義
declare -A TARGETS=(
    ["node_modules"]="find '$TARGET' -name 'node_modules' -type d -prune"
    ["__pycache__"]="find '$TARGET' -name '__pycache__' -type d"
    [".pyc files"]="find '$TARGET' -name '*.pyc' -type f"
    [".DS_Store"]="find '$TARGET' -name '.DS_Store' -type f"
    ["Thumbs.db"]="find '$TARGET' -name 'Thumbs.db' -type f"
    [".swp files"]="find '$TARGET' -name '*.swp' -type f"
    ["~ files"]="find '$TARGET' -name '*~' -type f"
)
 
total_saved=0
 
for name in "${!TARGETS[@]}"; do
    cmd="${TARGETS[$name]}"
    files=$(eval "$cmd" 2>/dev/null || true)
 
    if [[ -n "$files" ]]; then
        size=$(echo "$files" | xargs du -sh 2>/dev/null | tail -1 | awk '{print $1}')
        count=$(echo "$files" | wc -l | tr -d ' ')
        echo ""
        echo "--- $name ---"
        echo "  Found: $count item(s), Size: $size"
 
        if [[ "$DRY_RUN" == false ]]; then
            echo "$files" | xargs rm -rf
            echo "  Cleaned!"
        else
            echo "$files" | head -5
            [[ $count -gt 5 ]] && echo "  ... and $((count - 5)) more"
        fi
    fi
done
 
echo ""
echo "=== Cleanup Complete ==="

トラブルシューティング

よくあるエラーと解決策

エラー 原因 解決策
初期化エラー 設定ファイルの不備 設定ファイルのパスと形式を確認
タイムアウト ネットワーク遅延/リソース不足 タイムアウト値の調整、リトライ処理の追加
メモリ不足 データ量の増大 バッチ処理の導入、ページネーションの実装
権限エラー アクセス権限の不足 実行ユーザーの権限確認、設定の見直し
データ不整合 並行処理の競合 ロック機構の導入、トランザクション管理

デバッグの手順

  1. エラーメッセージの確認: スタックトレースを読み、発生箇所を特定する
  2. 再現手順の確立: 最小限のコードでエラーを再現する
  3. 仮説の立案: 考えられる原因をリストアップする
  4. 段階的な検証: ログ出力やデバッガを使って仮説を検証する
  5. 修正と回帰テスト: 修正後、関連する箇所のテストも実行する
# デバッグ用ユーティリティ
import logging
import traceback
from functools import wraps
 
# ロガーの設定
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s'
)
logger = logging.getLogger(__name__)
 
def debug_decorator(func):
    """関数の入出力をログ出力するデコレータ"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        logger.debug(f"呼び出し: {func.__name__}(args={args}, kwargs={kwargs})")
        try:
            result = func(*args, **kwargs)
            logger.debug(f"戻り値: {func.__name__} -> {result}")
            return result
        except Exception as e:
            logger.error(f"例外発生: {func.__name__}: {e}")
            logger.error(traceback.format_exc())
            raise
    return wrapper
 
@debug_decorator
def process_data(items):
    """データ処理(デバッグ対象)"""
    if not items:
        raise ValueError("空のデータ")
    return [item * 2 for item in items]

パフォーマンス問題の診断

パフォーマンス問題が発生した場合の診断手順:

  1. ボトルネックの特定: プロファイリングツールで計測
  2. メモリ使用量の確認: メモリリークの有無をチェック
  3. I/O待ちの確認: ディスクやネットワークI/Oの状況を確認
  4. 同時接続数の確認: コネクションプールの状態を確認
問題の種類 診断ツール 対策
CPU負荷 cProfile, py-spy アルゴリズム改善、並列化
メモリリーク tracemalloc, objgraph 参照の適切な解放
I/Oボトルネック strace, iostat 非同期I/O、キャッシュ
DB遅延 EXPLAIN, slow query log インデックス、クエリ最適化

設計判断ガイド

選択基準マトリクス

技術選択を行う際の判断基準を以下にまとめます。

判断基準 重視する場合 妥協できる場合
パフォーマンス リアルタイム処理、大規模データ 管理画面、バッチ処理
保守性 長期運用、チーム開発 プロトタイプ、短期プロジェクト
スケーラビリティ 成長が見込まれるサービス 社内ツール、固定ユーザー
セキュリティ 個人情報、金融データ 公開データ、社内利用
開発速度 MVP、市場投入スピード 品質重視、ミッションクリティカル

アーキテクチャパターンの選択

アーキテクチャ選択フロー
① チーム規模は?
├─ 小規模(1-5人)→ モノリス
└─ 大規模(10人+)→ ②へ
② デプロイ頻度は?
├─ 週1回以下 → モノリス + モジュール分割
└─ 毎日/複数回 → ③へ
③ チーム間の独立性は?
├─ 高い → マイクロサービス
└─ 中程度 → モジュラーモノリス

トレードオフの分析

技術的な判断には必ずトレードオフが伴います。以下の観点で分析を行いましょう:

1. 短期 vs 長期のコスト

  • 短期的に速い方法が長期的には技術的負債になることがある
  • 逆に、過剰な設計は短期的なコストが高く、プロジェクトの遅延を招く

2. 一貫性 vs 柔軟性

  • 統一された技術スタックは学習コストが低い
  • 多様な技術の採用は適材適所が可能だが、運用コストが増加

3. 抽象化のレベル

  • 高い抽象化は再利用性が高いが、デバッグが困難になる場合がある
  • 低い抽象化は直感的だが、コードの重複が発生しやすい
# 設計判断の記録テンプレート
class ArchitectureDecisionRecord:
    """ADR (Architecture Decision Record) の作成"""
 
    def __init__(self, title: str):
        self.title = title
        self.context = ""
        self.decision = ""
        self.consequences = []
        self.alternatives = []
 
    def set_context(self, context: str):
        """背景と課題の記述"""
        self.context = context
        return self
 
    def set_decision(self, decision: str):
        """決定内容の記述"""
        self.decision = decision
        return self
 
    def add_consequence(self, consequence: str, positive: bool = True):
        """結果の追加"""
        self.consequences.append({
            'description': consequence,
            'type': 'positive' if positive else 'negative'
        })
        return self
 
    def add_alternative(self, name: str, reason_rejected: str):
        """却下した代替案の追加"""
        self.alternatives.append({
            'name': name,
            'reason_rejected': reason_rejected
        })
        return self
 
    def to_markdown(self) -> str:
        """Markdown形式で出力"""
        md = f"# ADR: {self.title}\n\n"
        md += f"## 背景\n{self.context}\n\n"
        md += f"## 決定\n{self.decision}\n\n"
        md += "## 結果\n"
        for c in self.consequences:
            icon = "✅" if c['type'] == 'positive' else "⚠️"
            md += f"- {icon} {c['description']}\n"
        md += "\n## 却下した代替案\n"
        for a in self.alternatives:
            md += f"- **{a['name']}**: {a['reason_rejected']}\n"
        return md

実務での適用シナリオ

シナリオ1: スタートアップでのMVP開発

状況: 限られたリソースで素早くプロダクトをリリースする必要がある

アプローチ:

  • シンプルなアーキテクチャを選択
  • 必要最小限の機能に集中
  • 自動テストはクリティカルパスのみ
  • モニタリングは早期から導入

学んだ教訓:

  • 完璧を求めすぎない(YAGNI原則)
  • ユーザーフィードバックを早期に取得
  • 技術的負債は意識的に管理する

シナリオ2: レガシーシステムのモダナイゼーション

状況: 10年以上運用されているシステムを段階的に刷新する

アプローチ:

  • Strangler Fig パターンで段階的に移行
  • 既存のテストがない場合はCharacterization Testを先に作成
  • APIゲートウェイで新旧システムを共存
  • データ移行は段階的に実施
フェーズ 作業内容 期間目安 リスク
1. 調査 現状分析、依存関係の把握 2-4週間
2. 基盤 CI/CD構築、テスト環境 4-6週間
3. 移行開始 周辺機能から順次移行 3-6ヶ月
4. コア移行 中核機能の移行 6-12ヶ月
5. 完了 旧システム廃止 2-4週間

シナリオ3: 大規模チームでの開発

状況: 50人以上のエンジニアが同一プロダクトを開発する

アプローチ:

  • ドメイン駆動設計で境界を明確化
  • チームごとにオーナーシップを設定
  • 共通ライブラリはInner Source方式で管理
  • APIファーストで設計し、チーム間の依存を最小化
# チーム間のAPI契約定義
from dataclasses import dataclass
from typing import List, Optional
from enum import Enum
 
class Priority(Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    CRITICAL = "critical"
 
@dataclass
class APIContract:
    """チーム間のAPI契約"""
    endpoint: str
    method: str
    owner_team: str
    consumers: List[str]
    sla_ms: int  # レスポンスタイムSLA
    priority: Priority
 
    def validate_sla(self, actual_ms: int) -> bool:
        """SLA準拠の確認"""
        return actual_ms <= self.sla_ms
 
    def to_openapi(self) -> dict:
        """OpenAPI形式で出力"""
        return {
            'path': self.endpoint,
            'method': self.method,
            'x-owner': self.owner_team,
            'x-consumers': self.consumers,
            'x-sla-ms': self.sla_ms
        }
 
# 使用例
contracts = [
    APIContract(
        endpoint="/api/v1/users",
        method="GET",
        owner_team="user-team",
        consumers=["order-team", "notification-team"],
        sla_ms=200,
        priority=Priority.HIGH
    ),
    APIContract(
        endpoint="/api/v1/orders",
        method="POST",
        owner_team="order-team",
        consumers=["payment-team", "inventory-team"],
        sla_ms=500,
        priority=Priority.CRITICAL
    )
]

シナリオ4: パフォーマンスクリティカルなシステム

状況: ミリ秒単位のレスポンスが求められるシステム

最適化ポイント:

  1. キャッシュ戦略(L1: インメモリ、L2: Redis、L3: CDN)
  2. 非同期処理の活用
  3. コネクションプーリング
  4. クエリ最適化とインデックス設計
最適化手法 効果 実装コスト 適用場面
インメモリキャッシュ 頻繁にアクセスされるデータ
CDN 静的コンテンツ
非同期処理 I/O待ちが多い処理
DB最適化 クエリが遅い場合
コード最適化 低-中 CPU律速の場合

チーム開発での活用

コードレビューのチェックリスト

このトピックに関連するコードレビューで確認すべきポイント:

  • 命名規則が一貫しているか
  • エラーハンドリングが適切か
  • テストカバレッジは十分か
  • パフォーマンスへの影響はないか
  • セキュリティ上の問題はないか
  • ドキュメントは更新されているか

ナレッジ共有のベストプラクティス

方法 頻度 対象 効果
ペアプログラミング 随時 複雑なタスク 即時のフィードバック
テックトーク 週1回 チーム全体 知識の水平展開
ADR (設計記録) 都度 将来のメンバー 意思決定の透明性
振り返り 2週間ごと チーム全体 継続的改善
モブプログラミング 月1回 重要な設計 合意形成

技術的負債の管理

優先度マトリクス:

        影響度 高
          │
計画即座
的に
対応対応
記録次の
のみSprint
│
        影響度 低
    発生頻度 低  発生頻度 高

セキュリティの考慮事項

一般的な脆弱性と対策

脆弱性 リスクレベル 対策 検出方法
インジェクション攻撃 入力値のバリデーション・パラメータ化クエリ SAST/DAST
認証の不備 多要素認証・セッション管理の強化 ペネトレーションテスト
機密データの露出 暗号化・アクセス制御 セキュリティ監査
設定の不備 セキュリティヘッダー・最小権限の原則 構成スキャン
ログの不足 構造化ログ・監査証跡 ログ分析

セキュアコーディングのベストプラクティス

# セキュアコーディング例
import hashlib
import secrets
import hmac
from typing import Optional
 
class SecurityUtils:
    """セキュリティユーティリティ"""
 
    @staticmethod
    def generate_token(length: int = 32) -> str:
        """暗号学的に安全なトークン生成"""
        return secrets.token_urlsafe(length)
 
    @staticmethod
    def hash_password(password: str, salt: Optional[str] = None) -> tuple:
        """パスワードのハッシュ化"""
        if salt is None:
            salt = secrets.token_hex(16)
        hashed = hashlib.pbkdf2_hmac(
            'sha256',
            password.encode('utf-8'),
            salt.encode('utf-8'),
            iterations=100000
        )
        return hashed.hex(), salt
 
    @staticmethod
    def verify_password(password: str, hashed: str, salt: str) -> bool:
        """パスワードの検証"""
        new_hash, _ = SecurityUtils.hash_password(password, salt)
        return hmac.compare_digest(new_hash, hashed)
 
    @staticmethod
    def sanitize_input(value: str) -> str:
        """入力値のサニタイズ"""
        dangerous_chars = ['<', '>', '"', "'", '&', '\\']
        result = value
        for char in dangerous_chars:
            result = result.replace(char, '')
        return result.strip()
 
# 使用例
token = SecurityUtils.generate_token()
hashed, salt = SecurityUtils.hash_password("my_password")
is_valid = SecurityUtils.verify_password("my_password", hashed, salt)

セキュリティチェックリスト

  • 全ての入力値がバリデーションされている
  • 機密情報がログに出力されていない
  • HTTPS が強制されている
  • CORS ポリシーが適切に設定されている
  • 依存パッケージの脆弱性スキャンが実施されている
  • エラーメッセージに内部情報が含まれていない

FAQ

Q1: このトピックを学ぶ上で最も重要なポイントは何ですか?

実践的な経験を積むことが最も重要です。理論だけでなく、実際にコードを書いて動作を確認することで理解が深まります。

Q2: 初心者がよく陥る間違いは何ですか?

基礎を飛ばして応用に進むことです。このガイドで説明している基本概念をしっかり理解してから、次のステップに進むことをお勧めします。

Q3: 実務ではどのように活用されていますか?

このトピックの知識は、日常的な開発業務で頻繁に活用されます。特にコードレビューやアーキテクチャ設計の際に重要になります。


まとめ

操作 コマンド 主要オプション
ファイル作成 touch -t(時刻指定), -r(参照)
テキスト作成 echo >, cat << EOF >(上書き), >>(追記)
ディレクトリ作成 mkdir -p(ネスト), -m(パーミッション)
コピー cp -r(再帰), -a(アーカイブ), -i(確認)
移動/リネーム mv -i(確認), -n(上書き禁止)
削除 rm -r(再帰), -i(確認), trash推奨
ワイルドカード *, ?, [], {} extglob, globstar
同期 rsync -avh(基本), --delete, --exclude
リンク ln -s(シンボリック), -f(上書き)
比較 diff -u(unified), -r(再帰)

安全なファイル操作の鉄則

  1. rm -i をデフォルトにする -- エイリアスで常に確認付きに
  2. rm の代わりに trash を使う -- 復元可能な削除
  3. 変数展開前に空チェックする -- rm -rf "$UNDEFINED" の事故防止
  4. rsync は -n でドライランしてから実行 -- 予期しない削除を防ぐ
  5. ワイルドカードは ls で確認してから rm に使う -- 対象の事前確認
  6. 重要なファイルは cp --backup でバックアップ -- 上書き事故の防止
  7. 一括操作の前にバージョン管理(git)を活用 -- いつでも元に戻せるように

次に読むべきガイド


参考文献

  1. Shotts, W. "The Linux Command Line." 2nd Ed, Ch.4, No Starch Press, 2019.
  2. Ward, B. "How Linux Works." 3rd Ed, Ch.2, No Starch Press, 2021.
  3. rsync 公式マニュアル: https://rsync.samba.org/documentation.html
  4. GNU Coreutils マニュアル: https://www.gnu.org/software/coreutils/manual/
  5. Powers, S. "Unix Power Tools." 3rd Ed, O'Reilly, 2002.