基本ファイル管理 - cp/mv/rm/touch とワイルドカード【LPIC-1 103.3】

基本ファイル管理 - cp/mv/rm/touch とワイルドカード【LPIC-1 103.3】

この記事で達成できること

  • cp / mv / rm の主要オプション(-r -a -i -p -u -f)を使い分けられる
  • touch で空ファイルを作成し、タイムスタンプを更新できる
  • mkdir -p / rmdir でディレクトリを安全に作成・削除できる
  • ワイルドカード(* ? [ ] [!...])とブレース展開({ })を正しく書ける
  • グロブを展開するのはコマンドではなくシェルだと説明できる

LPIC-1 主題 103.3「基本的なファイル管理を行う」の中核。日常作業の 8 割を占めるファイル操作を、事故なく確実に行う型を押さえる。

どのコマンド・オプションを選ぶか

ファイル操作は「何をしたいか」と「事故をどう防ぐか」で選ぶ。下表が判断の起点になる。

やりたいこと コマンド 事故防止の定番
コピー cp -i(上書き確認)
バックアップ(属性保持) cp -a -a = 再帰+属性保持
移動・リネーム mv -i(上書き確認)
削除 rm -i(1件ずつ確認)
空ファイル作成・更新 touch 既存は中身を壊さない
ディレクトリ作成 mkdir -p 親ごと一括作成
空ディレクトリ削除 rmdir 空でなければ失敗で安全

迷ったら「破壊系(rm / mv の上書き)には -i を付ける」を基本姿勢にする。rmdir が空でないと失敗するのは欠点ではなく、誤削除を防ぐ安全弁だと理解しておく。

cp / mv / rm の使い方

cp - コピーとオプションの違い

cp はファイル・ディレクトリを複製する。ディレクトリには -r(再帰)が必須。バックアップ用途では属性まで保持する -a を使う。

cp file1.txt file2.txt
cp -r src/ backup/
cp -a src/ archive/
$ ls -l file2.txt
-rw-r--r-- 1 user user 0 May 30 10:00 file2.txt

主要オプションの意味は次のとおり。GNU coreutils の cp を前提とする。

オプション 意味
-r, -R ディレクトリを再帰的にコピー
-a アーカイブモード。-dR --preserve=all と同等(属性保持)
-i 上書き前に確認を求める
-p 更新時刻・所有者・パーミッションなどの属性を保持
-u コピー先が古い、または存在しない場合のみコピー(更新)

-r は「中身ごとコピー」、-a は「中身ごと+属性・シンボリックリンク・タイムスタンプも丸ごと保持」。単純な複製は -r、バックアップは -a と覚える。

-u(update)は差分同期に便利。cp -au src/ dst/ で「新しいものだけを属性保持でコピー」になり、簡易バックアップに使える。

mv - 移動とリネーム

mv は移動とリネームを兼ねる。同じディレクトリ内での mv old new がリネーム、別ディレクトリへの mv file dir/ が移動。上書きが怖い場面では -i を付ける。

mv draft.txt report.txt
mv report.txt /home/user/docs/
mv -i report.txt /home/user/docs/
$ mv -i report.txt /home/user/docs/
mv: overwrite '/home/user/docs/report.txt'? n
オプション 意味
-i 上書き前に確認を求める
-f 確認せず強制的に上書き(-i を打ち消す)

mvcp と違い、ディレクトリ移動に -r は不要。同一ファイルシステム内ならデータの実体は動かさずパス情報だけ書き換えるため高速。

rm - 削除と -rf の危険性

rm はファイルを削除する。ディレクトリ削除には -r、確認なしの強制削除には -f を使う。rm に「ゴミ箱」はなく、削除即消滅と考える。

rm unwanted.txt
rm -i unwanted.txt
rm -r olddir/
$ rm -i unwanted.txt
rm: remove regular file 'unwanted.txt'? y
オプション 意味
-r, -R ディレクトリを再帰的に削除
-f 存在確認・確認プロンプトを抑止し強制削除
-i 削除前に1件ずつ確認を求める

touch / mkdir / rmdir / file

touch - 空ファイル作成とタイムスタンプ更新

touch は存在しないファイルを空で作成し、既存ファイルにはアクセス時刻・更新時刻を現在時刻に更新する(中身は変えない)。

touch newfile.txt
touch existing.txt
touch -c missing.txt
$ ls -l --time-style=+%H:%M newfile.txt
-rw-r--r-- 1 user user 0 10:05 newfile.txt
オプション 意味
-a アクセス時刻のみ更新
-m 更新時刻(modification time)のみ更新
-c ファイルが存在しなければ作成しない
-t 指定した日時([[CC]YY]MMDDhhmm[.ss])に設定

既存ファイルに touch してもデータは消えない。ビルドの再実行を促す(make のタイムスタンプ判定)など、更新時刻の操作目的でも使う。

mkdir / rmdir - ディレクトリの作成と削除

mkdir はディレクトリを作る。途中の親ディレクトリがない深い階層は -p で一括作成する。rmdir空のディレクトリだけを削除する。

mkdir project
mkdir -p project/src/lib
rmdir project/src/lib
$ rmdir project
rmdir: failed to remove 'project': Directory not empty

-p がないと、存在しない親の下にはディレクトリを作れずエラーになる。rmdir が「空でないと失敗」するのは安全機構で、中身ごと消したいなら rm -r を使う(その分だけ危険も増す)。

file - 中身からファイル種別を判定する

file は拡張子ではなく中身を調べてファイルの種別を判定する。拡張子が偽っていても実体を見抜ける。

file report.pdf script.sh archive.gz photo
report.pdf:  PDF document, version 1.7
script.sh:   Bourne-Again shell script, ASCII text executable
archive.gz:  gzip compressed data
photo:       JPEG image data, JFIF standard 1.01

拡張子のない photo でも JPEG と判定できる。cat で開いて文字化けする前に file で種別を確認するのが安全な習慣。

ワイルドカードとシェル展開

ワイルドカード(グロブ)はファイル名のパターンを一括指定する仕組み。重要なのは、展開するのは cprm ではなくシェルだという点。シェルがパターンを実ファイル名に置き換えてからコマンドに渡す。

パターン マッチ対象
* 任意の0文字以上の文字列 *.txt → すべての .txt
? 任意の1文字 file?.txt → file1.txt, fileA.txt
[abc] 角括弧内のいずれか1文字 file[12].txt → file1.txt, file2.txt
[a-z] 範囲内のいずれか1文字 [a-c]* → a/b/c で始まる名前
[!abc] 角括弧内以外の1文字 file[!0].txt → file0.txt 以外

ブレース展開 { } はグロブと別物で、既存ファイルの有無に関係なく文字列を機械的に生成する。

echo file{A,B,C}.txt
echo {1..3}.log
mkdir -p project/{src,test,docs}
fileA.txt fileB.txt fileC.txt
1.log 2.log 3.log

{A,B,C} はカンマ区切りの列挙、{1..3} は連番。mkdir -p project/{src,test,docs} で 3 ディレクトリを一発生成できる。

ブレース展開はファイルが存在しなくても文字列を作る(生成系)。一方グロブ * ? [ ] は既存ファイル名へのマッチ(検索系)。*.txt は .txt が1つもなければマッチせず、デフォルトの bash ではパターン文字列がそのままコマンドに渡る点に注意。

ls *.nonexistent
echo *.nonexistent
ls: cannot access '*.nonexistent': No such file or directory
*.nonexistent

グロブが0件のとき、bash はデフォルトでパターンをそのまま渡す(echo はその文字列を表示し、ls は「そんなファイルはない」と言う)。これは shopt -s nullglob を設定すると「0件なら空に展開」へ変えられる。

よくあるミスと対処

実務・試験の両方でつまずきやすい点を整理する。

  • cp でディレクトリに -r を付け忘れる: cp dir/ dst/omitting directory エラー。ディレクトリコピーは常に -r-a
  • -r-a を混同する: 単純複製は -r、所有者・パーミッション・リンク・時刻まで保持するバックアップは -a-r だけだと属性が変わる。
  • mv で無確認に上書きする: デフォルトの mv は既存ファイルを黙って上書きする。重要ファイルには -i を習慣化する。
  • rm * をルートや重要ディレクトリで実行: グロブを展開するのはシェル。実行前に echo rm * のように echo を前置して、何に展開されるか確認すると安全。
  • rmdir で「空でない」エラーに戸惑う: 仕様どおりの安全動作。中身ごと消すなら rm -r、ただし対象を必ず確認。

トラブルシューティング

症状: cp で「omitting directory」と出てコピーされない

原因: ディレクトリを -r(または -a)なしでコピーしようとしている

確認:

file src

対処: ディレクトリなら cp -r src/ dst/、属性も保つなら cp -a src/ dst/ を使う。

症状: rm -rf を実行したらファイルが消えてしまった

原因: rm -rf は確認なしで再帰削除する。rm に削除取り消しはない

確認:

echo rm -rf target/

対処: 実行前に echo を前置して展開結果を目視する。不安なら -i を併用(rm -ri)。消えたファイルはバックアップからのみ復旧可能。

症状: ワイルドカードを書いたのにマッチしない/パターンがそのまま表示される

原因: 一致するファイルが0件。bash はデフォルトでパターン文字列をそのまま渡す

確認:

shopt nullglob
ls -d *.txt

対処: 対象ディレクトリと拡張子を見直す。0件時に空展開させたい場合は shopt -s nullglob を設定する。

作業完了チェックリスト

  • [ ] cp -r / cp -a の違いを説明して使い分けた
  • [ ] mv -i / rm -i で上書き・削除前の確認を有効にした
  • [ ] touch で空ファイル作成とタイムスタンプ更新を確認した
  • [ ] mkdir -prmdir の挙動の違いを確認した
  • [ ] * ? [ ] とブレース展開 { } を書き分けた
  • [ ] グロブを展開するのがシェルだと理解した

まとめ

場面 コマンド ポイント
コピー cp -r / cp -a -a は属性まで保持
移動・リネーム mv -i デフォルトは黙って上書き
削除 rm -ri 取り消し不可、-rf は最大注意
作成・更新 touch / mkdir -p 既存の中身は壊さない
空ディレクトリ削除 rmdir 空でなければ失敗(安全)
種別判定 file 拡張子でなく中身で判定
一括指定 * ? [ ] { } 展開するのはシェル

基本ファイル管理は LPIC-1 で最も使用頻度が高い領域。ここを固めたら、ファイルの実体を指すリンク機構や、FHS とファイル検索へ進むと体系が完成する。

次に読む