- 技術 💻
cp・rm・mvコマンドの使い方|オプション早見表とエラーの直し方
結論
cpは複製、mvは名前と場所の変更、rmは削除です。rmで消したものはゴミ箱に入りません。どれも、同じ名前のファイルを確認なしで上書きします。
この記事でわかること
- 3コマンドのオプション早見表と実行結果
- エラー15種の原文(英語・日本語)と直し方
- 上書き・削除の事故を防ぐ4つの設定
cp は元を残したまま複製を作り、mv は元の名前を付け替え、rm は名前そのものを消します。
flowchart LR
F[元のファイル] --> C[cp:複製を作る<br>元も残る]
F --> M[mv:名前と場所を変える<br>元の名前は消える]
F --> R[rm:名前を消す<br>ゴミ箱に入らない]
よく使う形を、検索の多い順にまとめます。
| やりたいこと | コマンド | 補足 |
|---|---|---|
| ファイルをコピーする | cp a.txt b.txt |
b.txt があれば確認なしで上書き |
| ディレクトリごとコピーする | cp -r src dst |
dst があると dst/src になる |
| ファイルを消す | rm a.txt |
ゴミ箱に入らない |
| ディレクトリごと消す | rm -r dir |
-f を付けると確認もエラーも出ない |
| 名前を変える | mv old.txt new.txt |
new.txt があれば上書き |
| ディレクトリへ移動する | mv a.txt dir/ |
複数のファイルもまとめて移せる |
| 時刻・権限ごとコピーする | cp -a src dst |
バックアップ向き |
| 上書きしない | cp --update=none |
-n は版で動きが違う |
| 上書き前に退避する | cp -b / mv -b |
元のファイルが 名前~ に残る |
確認環境:Ubuntu 24.04・GNU coreutils 9.4(パッケージ 9.4-3ubuntu6.2)・bash 5.2.21・ext4 と tmpfs。cp・rm・mv のすべての例を実際に実行し、出力をそのまま載せています。日本語のメッセージは、Ubuntu の日本語言語パック(language-pack-ja-base)の翻訳を読み込んで LANG=ja_JP.UTF-8 で出したものです。権限のエラーは nobody ユーザーで実行しました。Mac(BSD 系)の動きは Apple が公開している file_cmds のマニュアル(cp.1・rm.1・mv.1)、Windows のコマンドは Microsoft Learn、版ごとの違いは coreutils の NEWS で確かめました(確認日 2026年10月18日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「cp・rm・mvコマンドの使い方|オプション早見表とエラーの直し方」
cp・rm・mvコマンドのオプション早見表
3つのコマンドは同じ名前のオプションが多く、意味もほぼそろっています。cp --help・rm --help・mv --help(coreutils 9.4)で確かめた一覧です。
| オプション | cp | mv | rm |
|---|---|---|---|
-r / -R |
ディレクトリを中身ごとコピー | (不要。ディレクトリもそのまま移る) | ディレクトリを中身ごと削除 |
-a |
時刻・権限・リンクを保ってコピー(-dR --preserve=all) |
― | ― |
-p |
権限・所有者・時刻を保つ | ― | ― |
-i |
上書きの前に確認 | 上書きの前に確認 | 1件ずつ確認 |
-I |
― | ― | 4件以上か再帰のときに1回だけ確認 |
-f |
開けない上書き先を消して作り直す | 確認せずに上書き | 確認せず、無いファイルも無視 |
-n |
上書きしない | 上書きしない | ― |
--update=none |
上書きしない(終了コード0) | 上書きしない(終了コード0) | ― |
-u |
元のほうが新しいときだけ上書き | 元のほうが新しいときだけ上書き | ― |
-b / --backup |
上書きされる側を退避 | 上書きされる側を退避 | ― |
-T |
最後の引数をディレクトリとみなさない | 最後の引数をディレクトリとみなさない | ― |
-t DIR |
コピー先を先に書く | 移動先を先に書く | ― |
-v |
何をしたかを表示 | 何をしたかを表示 | 何をしたかを表示 |
-d |
シンボリックリンクをリンクのまま | ― | 空のディレクトリを削除 |
-L / -P |
リンク先をたどる/たどらない | ― | ― |
--parents |
元のパスごとコピー先に作る | ― | ― |
-i・-f・-n は、cp と mv で意味が違う点に注意します。 mv はマニュアルに「-i・-f・-n は最後に書いたものが勝つ」とあり、mv -i -f は確認しません。rm も、alias rm='rm -i' のまま rm -f と打つと後の -f が勝ち、確認なしで消えました。cp の -f は「上書き先を開けないときに消して作り直す」という別の意味で、-i を打ち消しません(後の「上書き事故を防ぐ設定」で実例を載せます)。
関連記事「Linuxコマンド一覧|100個をカテゴリ別に実行結果つきで解説」で扱っています。
cpコマンドの使い方
ファイルをコピーする
$ cp a.txt b.txt
$ cp -v a.txt c.txt
'a.txt' -> 'c.txt'
$ cp a.txt backup/
$ cp -v a.txt b.txt c.txt backup
'a.txt' -> 'backup/a.txt'
'b.txt' -> 'backup/b.txt'
'c.txt' -> 'backup/c.txt'
成功したときは何も表示されません。-v を付けると、コピー元とコピー先が1行ずつ出ます。最後の引数が既にあるディレクトリなら、その中に同じ名前で入ります。 3つ以上の引数を並べたときは、最後の引数がディレクトリでないとエラーになります。
$ cp a.txt b.txt nodir
cp: target 'nodir': No such file or directory
$ cp a.txt b.txt c
cp: target 'c': Not a directory
ディレクトリをコピーする(cp -r)
ディレクトリは -r を付けないとコピーされません。
$ cp src dst
cp: -r not specified; omitting directory 'src'
$ cp -r src dst
$ tree -a dst
dst
|-- .hidden
|-- one.txt
`-- sub
`-- two.txt
コピー先があるかどうかで結果が変わる
cp -r src dst は、dst が無ければ「dst を作って中身を入れる」、dst があれば「dst の中に src を作る」動きになります。 同じコマンドを2回打つと、2回目は1段深くコピーされます。
flowchart TD
A[cp -r src dst] --> B{dst はある?}
B -->|無い| C[dst ができる<br>中身は dst の直下]
B -->|ある| D[dst/src ができる<br>1段深くなる]
$ cp -r src dst # 2回目
$ tree -a dst
dst
|-- .hidden
|-- one.txt
|-- src
| |-- .hidden
| |-- one.txt
| `-- sub
| `-- two.txt
`-- sub
`-- two.txt
dst があるかどうかに関係なく「中身だけ」をコピーしたいときは、次の3通りがあります。
| 書き方 | 結果 | 注意 |
|---|---|---|
cp -r src/. dst |
中身だけ(隠しファイルも) | dst が無ければ作られる |
cp -rT src dst |
中身だけ(隠しファイルも) | dst を「名前」として扱う |
cp -r src/* dst |
中身だけ(隠しファイルは除く) | * は .hidden に一致しない |
$ cp -r src/* dst4
$ tree -a dst4
dst4
|-- one.txt
`-- sub
`-- two.txt
src/* では .hidden が抜けました。* はシェルが展開するもので、bash の初期設定ではドットで始まる名前に一致しないためです。
末尾のスラッシュ(src と src/)
Linux の cp(GNU coreutils)では、cp -r src/ dst と cp -r src dst は同じ結果です。 1回目は dst2 の直下に中身が入り、2回目は dst2/src ができました。
$ cp -r src/ dst2
$ cp -r src/ dst2
$ tree -a dst2
dst2
|-- .hidden
|-- one.txt
|-- src
| |-- .hidden
| |-- one.txt
| `-- sub
| `-- two.txt
`-- sub
`-- two.txt
末尾のスラッシュで結果が変わるのは、Mac の cp と rsync です。Mac の cp のマニュアル(-R の説明)には「source_file が / で終わるときは、ディレクトリそのものではなく中身がコピーされる」と書かれています。rsync 3.2.7 でも次のように変わりました。
$ rsync -a src dstA
$ tree dstA
dstA
`-- src
|-- one.txt
`-- sub
`-- two.txt
$ rsync -a src/ dstB
$ tree dstB
dstB
|-- one.txt
`-- sub
`-- two.txt
cp -r src/ dst と cp -r src dst は同じ。結果を決めるのは dst があるかどうかcp -r src/. dst か cp -rT src dstGNU coreutils 9.4 で確認
src/ と書くと中身だけ、src と書くとディレクトリごとsrc/. を使うMac の cp は man の -R の説明、rsync は 3.2.7 で確認
cp -a と cp -r の違い(時刻・権限・リンク)
-r は中身だけを写し、-a は時刻・権限・所有者・シンボリックリンクまで写します。 時刻を 2026-01-02、権限を 640 にしたファイルで比べました。
$ ls -l --time-style=long-iso orig.txt link.txt
lrwxrwxrwx 1 root root 8 2026-10-18 13:17 link.txt -> orig.txt
-rw-r----- 1 root root 5 2026-01-02 03:04 orig.txt
$ cp orig.txt r.txt
$ cp -p orig.txt p.txt
$ cp -a orig.txt a.txt
$ ls -l --time-style=long-iso r.txt p.txt a.txt
-rw-r----- 1 root root 5 2026-01-02 03:04 a.txt
-rw-r----- 1 root root 5 2026-01-02 03:04 p.txt
-rw-r----- 1 root root 5 2026-10-18 13:17 r.txt
オプションなしの r.txt は、時刻がコピーした時刻に変わりました。シンボリックリンクをコピーしたときの違いです。
$ cp link.txt l1.txt
$ cp -P link.txt l2.txt
$ cp -a link.txt l3.txt
$ ls -l --time-style=long-iso l1.txt l2.txt l3.txt
-rw-r----- 1 root root 5 2026-10-18 13:17 l1.txt
lrwxrwxrwx 1 root root 8 2026-10-18 13:17 l2.txt -> orig.txt
lrwxrwxrwx 1 root root 8 2026-10-18 13:17 l3.txt -> orig.txt
オプションなしの cp はリンク先の中身を写し、-P・-a はリンクのまま写します。-r でディレクトリをコピーしたときは、中のリンクはリンクのまま写り、-rL を付けるとリンク先の中身に置き換わりました。
| 用途 | 選ぶオプション | 理由 |
|---|---|---|
| 設定ファイルを試しに写す | cp(なし) |
新しいファイルとして扱える |
| バックアップを取る | cp -a |
時刻・権限・リンクを保つ |
| 別のユーザーに渡す | cp -r |
所有者を自分にする |
| リンクの先の実体をまとめたい | cp -rL |
リンクを中身に置き換える |
関連記事「Linuxシンボリックリンクln -sの使い方|作成・削除・確認一覧」で扱っています。
便利なオプション(--parents・-t・-u)
--parents は、元のパスをコピー先に作ります。コピー先は既にあるディレクトリでないとエラーになります。
$ cp --parents proj/src/main/App.java out
cp: with --parents, the destination must be a directory
Try 'cp --help' for more information.
$ mkdir out
$ cp --parents proj/src/main/App.java out
$ tree out
out
`-- proj
`-- src
`-- main
`-- App.java
-t はコピー先を先に書く形です。find や xargs で、コピー元をあとから並べたいときに使います。
$ cp -t out proj/docs/a.md
$ ls out
a.md
proj
-u は、コピー元のほうが新しいときだけ上書きします。a.txt(10月1日)・b.txt(10月10日)のときは何も起きず、a.txt を10月20日にすると上書きされました。
$ cp -uv a.txt b.txt
$ cat b.txt
old
$ touch -d '2026-10-20' a.txt
$ cp -uv a.txt b.txt
'a.txt' -> 'b.txt'
$ cat b.txt
new
rmコマンドの使い方
ファイルを消す・ディレクトリを消す
$ rm a.txt
$ rm -v b.txt
removed 'b.txt'
$ rm emp
rm: cannot remove 'emp': Is a directory
$ rm -d emp
$ rm -d full
rm: cannot remove 'full': Directory not empty
$ rm -rv full
removed 'full/x'
removed 'full/sub/y'
removed directory 'full/sub'
removed directory 'full'
rm は、オプションなしではディレクトリを消しません。 空のディレクトリは -d(または rmdir)、中身ごと消すときは -r を付けます。-r は中の項目から順に消していきます。
rm -i と rm -I(確認してから消す)
-i は1件ずつ、-I は「4件以上」か「再帰で消す」ときに1回だけ確認します。
$ rm -i a b
rm: remove regular empty file 'a'? y
rm: remove regular empty file 'b'? n
$ rm -I b c d f
rm: remove 4 arguments? y
$ rm -rI dd
rm: remove 1 argument recursively? n
-I は3件までなら確認しません。 rm -I b c d(3件)は確認なしで消えました。rm -ri は、ディレクトリに入る前と消す前にも聞きます。
$ rm -ri dd
rm: descend into directory 'dd'? y
rm: descend into directory 'dd/x'? y
rm: remove regular empty file 'dd/x/f'? y
rm: remove directory 'dd/x'? y
rm: remove directory 'dd'? y
書き込みを禁止したファイル(444)を root 以外のユーザーで消すと、端末から実行したときだけ確認されます。パイプやスクリプトから実行したときは、確認なしで消えました。
$ rm e
rm: remove write-protected regular empty file 'e'? n
rm -f(確認もエラーも出さない)
-f は、無いファイルを指定してもエラーにせず、終了コードも0のままにします。
$ rm nofile.txt
rm: cannot remove 'nofile.txt': No such file or directory
$ rm -f nofile.txt; echo "status=$?"
status=0
-f は「確認」と「無いファイルのエラー」を消すだけで、権限の壁は越えません。 書き込みできないディレクトリの中は、-rf でも消せませんでした(「よくあるエラー」の Permission denied の節)。
ハイフンや空白で始まる名前を消す
-foo という名前のファイルは、オプションと見なされます。rm 自身が直し方を表示しました。
$ rm -foo
rm: invalid option -- 'o'
Try 'rm ./-foo' to remove the file '-foo'.
Try 'rm --help' for more information.
$ rm -- -foo
$ rm ./-f
$ rm my file.txt
rm: cannot remove 'my': No such file or directory
rm: cannot remove 'file.txt': No such file or directory
$ rm 'my file.txt'
-- は「ここから後はオプションではない」という印です。空白を含む名前は引用符で囲みます。
rm -rfの危険と、消したファイルが戻らない理由
rm -rf は確認なしで全部消す
rm -rf は、確認なしで、エラーも黙らせて、指定したディレクトリの下をすべて消します。 打ち間違いや変数の空がそのまま大きな削除になります。
rm -rf $DIR/*(DIR が空だと /* になる)rm -rf -- "${DIR:?}"/*(空ならシェルが止める)bash の ${変数:?} は、空か未設定のときにエラーで止まる
rm -rf ~ /tmp/work(空白が1つ入った)ls -d ~/tmp/work で対象を表示し、同じパスで消す引数は空白で区切られる。~ と /tmp/work の2つになる
cd build; rm -rf *(cd に失敗しても続く)cd build && rm -rf ./*; は前の失敗を見ない。&& は成功したときだけ次へ進む
GNU の rm には、/ を消させない安全装置(--preserve-root)が既定で入っています。rm --help の説明は「do not remove '/' (default)」です。coreutils のメッセージ一覧(翻訳カタログ)には、この安全装置が止めたときの文として次の2つがあります(%s に '/' が入ります)。
it is dangerous to operate recursively on %s
use --no-preserve-root to override this failsafe
ただし守られるのは / そのものだけです。/* のようにシェルが展開した名前(/bin・/etc など)は1つずつ渡されるので、この装置では止まりません。
--one-file-system と --preserve-root=all は、別のファイルシステム(マウントした領域)に入らないようにします。data の下に tmpfs をマウントして試しました。
$ rm -r --one-file-system data
rm: skipping 'data/mnt', since it's on a different device
$ find data
data
data/mnt
data/mnt/important
$ rm -r --preserve-root=all data/mnt
rm: skipping 'data/mnt', since it's on a different device
rm: and --preserve-root=all is in effect
消したファイルが戻らない理由
rm は「中身を消す」のではなく、ディレクトリから「名前」を外すコマンドです(unlink)。 名前が0個になり、どのプロセスも開いていなければ、その領域は空きとして再利用されます。ゴミ箱に移す仕組みは無く、元に戻すコマンドもありません。rm --help には「中身の一部を専門的な手段で取り出せる可能性はある。確実に読めなくするには shred を使う」と書かれています。つまり、普通の操作で戻す方法は無く、中身が完全に消える保証もありません。
ハードリンクで名前を2つにしてから1つ消すと、中身は残りました。ls -i の左の数字(inode 番号)が同じで、リンク数が 2 から 1 に減っています。
$ ls -li a.txt hard.txt
3427142 -rw-r--r-- 2 root root 10 Oct 18 13:18 a.txt
3427142 -rw-r--r-- 2 root root 10 Oct 18 13:18 hard.txt
$ rm a.txt
$ ls -li hard.txt
3427142 -rw-r--r-- 1 root root 10 Oct 18 13:18 hard.txt
$ cat hard.txt
important
開いたままのファイルは取り戻せることがある
消したファイルを、まだどこかのプロセスが開いているなら、中身はまだ残っています。 シェルでファイルを開いたまま rm し、/proc から取り戻しました。
$ exec 3< big.log # このシェルが big.log を開いたままにする
$ rm big.log
$ ls big.log
ls: cannot access 'big.log': No such file or directory
$ ls -l /proc/$$/fd/3
lr-x------ 1 root root 64 Oct 18 13:18 /proc/1905/fd/3 -> /home/user/work/big.log (deleted)
$ cp /proc/$$/fd/3 restored.log && wc -l restored.log
100000 restored.log
ログを書き続けているサーバーのログを rm した直後は、この方法が使えることがあります。プロセスを止めると取り戻せません。関連記事「Linuxでrmしても容量が減らない原因と対処法」で扱っています。
ゴミ箱に送るコマンド(trash-cli)
戻せる削除にしたいときは、ゴミ箱(~/.local/share/Trash)に送る trash-cli が使えます。sudo apt install trash-cli か pipx install trash-cli で入ります。trash-cli 0.26.9.29 の出力です。
$ trash-put -v report.txt old
trash-put: 'report.txt' trashed in ~/.local/share/Trash
trash-put: 'old' trashed in ~/.local/share/Trash
$ trash-list
2026-10-18 13:20:38 /home/user/work/old
2026-10-18 13:20:38 /home/user/work/report.txt
$ trash-restore
0 2026-10-18 13:20:38 /home/user/work/old
1 2026-10-18 13:20:38 /home/user/work/report.txt
What file to restore [0..1]: 0
$ ls
old
$ trash-empty -f
trash-put はディレクトリにも -r が要りません。README の FAQ は、この違いがあるので alias rm=trash-put にはしないよう勧めています。
- 1消す前に、同じパスで
ls -laを打って対象を目で見たls の矢印キーで呼び出し、ls を rm に書き換えると打ち間違いが減る - 2
pwdで今いる場所を確かめた相対パスの./*は、今いる場所で意味が変わる - 3変数を使うなら
"${DIR:?}"の形にした空のまま実行されるのを防ぐ - 4大事なものは、消す前に
cp -aかmvで退避したrm には取り消しが無い - 5
-fが本当に要るか考えたまず-rIで1回確認を挟む
mvコマンドの使い方
名前を変える・移動する
$ mv -v a.txt renamed.txt
renamed 'a.txt' -> 'renamed.txt'
$ mv -v renamed.txt dir/
renamed 'renamed.txt' -> 'dir/renamed.txt'
$ mv -v b.txt dir/new_name.txt
renamed 'b.txt' -> 'dir/new_name.txt'
mv には「名前を変える」と「移動する」の区別がありません。 最後の引数が既にあるディレクトリなら中へ移し、そうでなければその名前に変えます。移動しながら名前も変えられます。
ディレクトリも -r なしでそのまま移ります。移動先に同じ名前のファイルがあると、確認なしで上書きします。
$ mv x.txt y.txt
$ cat y.txt
X
同じディスクの中なら一瞬で終わる
同じファイルシステムの中の mv は、データを動かさずに名前だけを付け替えます。50MB のファイルで、inode 番号は変わらず、0.002秒で終わりました。別のファイルシステム(tmpfs から ext4)へ移すと、-v の表示が「copied」と「removed」の2行になり、inode 番号が変わりました。
$ ls -i same.bin; time mv same.bin moved.bin; ls -i moved.bin
3424658 same.bin
real 0m0.002s
3424658 moved.bin
$ mv -v /dev/shm/big.bin ./big.bin
copied '/dev/shm/big.bin' -> './big.bin'
removed '/dev/shm/big.bin'
coreutils のマニュアルによると、別のファイルシステムへの mv は cp -a と同じようにコピーし、成功したときだけ元を消します。コピーに失敗したときは、途中までのコピーを残しません。--no-copy を付けると、コピーせずにエラーで止まります。
$ mv --no-copy big.bin /dev/shm/big.bin
mv: cannot move 'big.bin' to '/dev/shm/big.bin': Invalid cross-device link
ディレクトリを移すときの決まり
| 状況 | 結果 |
|---|---|
| 移動先が無い | その名前に変わる |
| 移動先が既にあるディレクトリ | その中に入る |
| 移動先の中に、同じ名前の空のディレクトリがある | 置き換わる |
| 移動先の中に、同じ名前の中身のあるディレクトリがある | Directory not empty で止まる |
| 移動先が普通のファイル | cannot overwrite non-directory で止まる |
-T を付けた |
移動先を「名前」として扱う(空なら置き換え) |
$ mv src dst
mv: cannot overwrite 'dst/src': Directory not empty
$ mv -v src dst2 # dst2/src は空
renamed 'src' -> 'dst2/src'
$ mv -T A B # B は空のディレクトリ
$ ls B
a
まとめて名前を変える
mv は1回に1つの名前しか変えられないので、複数の名前を変えるときは for 文と組み合わせます。
for f in *.JPG; do mv -v -- "$f" "${f%.JPG}.jpg"; done
renamed 'IMG_001.JPG' -> 'IMG_001.jpg'
renamed 'IMG_002.JPG' -> 'IMG_002.jpg'
renamed 'IMG_003.JPG' -> 'IMG_003.jpg'
${f%.JPG} は、変数 f の末尾から .JPG を取り除いた値です。日付を付けて退避する形もよく使います。
$ mv -v report.txt report_$(date +%Y%m%d).txt
renamed 'report.txt' -> 'report_20261018.txt'
上書き事故を防ぐ設定(alias・-i・-n・--backup)
cp と mv は、同じ名前があると確認なしで上書きします。防ぐ方法は4つあります。
| 方法 | 書き方 | 向いている場面 |
|---|---|---|
| 確認を出す | cp -i / mv -i |
手で打つとき |
| 上書きしない | cp --update=none |
スクリプト |
| 退避してから上書き | cp -b / --backup=numbered |
設定ファイルの更新 |
| いつも確認を出す | alias cp='cp -i' |
対話のシェル全体 |
-i:上書きの前に確認する
$ cp -i a.txt b.txt
cp: overwrite 'b.txt'? n
$ cat b.txt
old
n と答えると、終了コードは 1 になりました(coreutils 9.2 からの動き。NEWS より)。
-n と --update=none:上書きしない
-n は、coreutils の版と配布元で動きが違います。 Ubuntu 24.04 の cp は警告を出して終了コード 0、mv は「not replacing」と出して終了コード 1 でした。
$ cp -n a.txt b.txt; echo "status=$?"
cp: warning: behavior of -n is non-portable and may change in future; use --update=none instead
status=0
$ mv -n x.txt y.txt; echo status=$?
mv: not replacing 'y.txt'
status=1
$ cp --update=none a.txt b.txt; echo "status=$?"
status=0
| 版 | cp -n で上書きしなかったとき |
出典 |
|---|---|---|
| coreutils 9.1 まで | 黙ってスキップ・終了コード 0 | NEWS |
| coreutils 9.2〜9.4 | メッセージを出し・終了コード 1 | NEWS |
| Debian・Ubuntu の 9.4 | 警告を出し・終了コード 0(cp だけ元に戻した) | Debian の変更履歴・上の実行結果 |
| coreutils 9.5 以降 | 黙ってスキップ・終了コード 0 | NEWS |
警告が勧めるとおり、スクリプトでは --update=none(9.3 から)を使うと版による違いが出ません。9.5 で入った --update=none-fail は「上書きしなかったら失敗にする」形で、9.4 では invalid argument 'none-fail' になりました。
--backup:上書きされる側を残す
$ cp -b new1 conf
$ cat conf~
v1
$ cp --backup=numbered -v new2 conf
'new2' -> 'conf' (backup: 'conf.~1~')
$ cp --backup=numbered -v new3 conf
'new3' -> 'conf' (backup: 'conf.~2~')
$ cp -b --suffix=.$(date +%Y%m%d) new1 conf; ls conf*
conf
conf.20261018
--backup= の値 |
退避の名前 |
|---|---|
simple(never) |
conf~ |
numbered(t) |
conf.~1~・conf.~2~ と番号が増える |
existing(nil)。-b だけのときの既定 |
番号付きが既にあれば番号、無ければ ~ |
none(off) |
退避しない |
-S(--suffix)で ~ を別の文字に変えられます。既定は環境変数 VERSION_CONTROL・SIMPLE_BACKUP_SUFFIX で変わります(coreutils のマニュアル「Backup options」)。mv の -b も同じで、renamed 'x.txt' -> 'y.txt' (backup: 'y.txt~') と表示されました。
alias で -i をいつも付ける
RHEL 系の root の .bashrc には alias rm='rm -i' などが入っていることがあります。Ubuntu の初期の .bashrc(/etc/skel)には、cp・rm・mv の alias はありませんでした。~/.bashrc に書くと、対話のシェルでいつも確認が出ます。
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
$ type rm cp mv
rm is aliased to `rm -i'
cp is aliased to `cp -i'
mv is aliased to `mv -i'
$ rm -f c # rm は後の -f が勝ち、確認なしで消えた
$ cp -f a b
cp: overwrite 'b'?
$ \cp a b # 先頭に \ を付けると alias を使わない
$ command cp a b # command でも同じ
alias で cp -i にしていると、cp -f でも確認が出ます。 cp の -f は確認を消すオプションではないためです。一度だけ確認なしで上書きしたいときは \cp か command cp を使います。alias はスクリプトの中では使われないので、スクリプトの安全は --update=none や -b で守ります。
関連記事「Linux alias設定と.bashrcの書き方|おすすめエイリアス50選」で扱っています。
cp・rm・mvのよくあるエラーと直し方
実際に出したエラーの原文です。日本語の環境(LANG=ja_JP.UTF-8)では、右の列の日本語で表示されます。
| エラー(英語の原文) | 日本語の表示 | 直し方 |
|---|---|---|
cp: -r not specified; omitting directory 'src' |
-r が指定されていません; ディレクトリ 'src' をスキップしています |
cp -r |
rm: cannot remove 'emp': Is a directory |
'emp' を削除できません: ディレクトリです |
rm -r(空なら rm -d) |
cp: cannot stat 'missing.txt': No such file or directory |
'missing.txt' を stat できません: そのようなファイルやディレクトリはありません |
名前と今いる場所を確かめる |
cp: cannot create regular file 'ro/s2.txt': Permission denied |
通常ファイル 'ro/s2.txt' を作成できません: 許可がありません |
書き込み先の権限を確かめる |
rm: cannot remove 'other/f': Permission denied |
'other/f' を削除できません: 許可がありません |
親ディレクトリの書き込み権を確かめる |
rmdir: failed to remove 'full': Directory not empty |
'full' を削除できません: ディレクトリは空ではありません |
中身を確かめて rm -r |
mv: cannot overwrite 'dst/src': Directory not empty |
'dst/src' を上書きできません: ディレクトリは空ではありません |
中身をまとめるなら cp -a/rsync |
mv: cannot move 'src' to a subdirectory of itself, 'src/sub/src' |
'src' を自分自身のサブディレクトリ 'src/sub/src' に移動できません |
移動先を外の場所にする |
cp: cannot copy a directory, 'src', into itself, 'src/sub/src' |
ディレクトリ 'src' を自分自身 'src/sub/src' にコピーできません |
コピー先を外の場所にする |
bash: /usr/bin/rm: Argument list too long |
/usr/bin/rm: 引数リストが長すぎます |
find -delete か xargs |
cp: 'a.txt' and 'a.txt' are the same file |
'a.txt' と 'a.txt' は同じファイルです |
別の名前か別の場所にする |
cp: target 'c': Not a directory |
ターゲット 'c': ディレクトリではありません |
最後の引数をディレクトリにする |
mv: cannot overwrite non-directory 'file' with directory 'd2' |
ディレクトリではない 'file' をディレクトリ 'd2' で上書きすることはできません |
名前を変えるか file を退避 |
rm: invalid option -- 'o' |
― | rm -- -foo か rm ./-foo |
mv: cannot move 'lnk/' to 'C': Not a directory |
'lnk/' から 'C' へ移動できません: ディレクトリではありません |
リンクを移すなら末尾の / を外す |
No such file or directory
いちばん多いのは、名前の打ち間違いと、今いる場所の勘違いです。pwd と ls で確かめ、名前は Tab キーで補完すると打ち間違いが減ります。空白を含む名前を引用符で囲み忘れたときも、名前が2つに分かれてこのエラーになります(「ハイフンや空白で始まる名前を消す」の節)。
Permission denied
ファイルを作る・消す・移すのに要るのは、そのファイルではなく「入っているディレクトリ」の書き込み権です。 nobody ユーザーで、root のディレクトリに対して試しました。
$ cp ro/s.txt ro/s2.txt
cp: cannot create regular file 'ro/s2.txt': Permission denied
$ rm -f other/f
rm: cannot remove 'other/f': Permission denied
$ mv ro/f ./f
mv: cannot move 'ro/f' to './f': Permission denied
$ rm -rf locked # locked/d が 555(書き込み不可)
rm: cannot remove 'locked/d/f': Permission denied
ls -ld ディレクトリ名 で、所有者と書き込み権(w)を確かめます。自分のものなら chmod u+w、ほかのユーザーのものなら所有者に頼むか sudo を使います。-f を付けても、この壁は越えません。
関連記事「chmodの755と644の意味|用途別パーミッション早見表」で扱っています。
Directory not empty
rmdir と rm -d は空のディレクトリしか消しません。中身は ls -A で隠しファイルまで見られます。mv で出たときは、移動先に同じ名前の中身のあるディレクトリがあります。2つの中身を合わせたいときは、mv ではなく cp -a src/. dst/src/ でコピーしてから元を消すか、rsync -a src/ dst/src/ を使います。
cannot move to a subdirectory of itself
ディレクトリを自分自身の下へ移そう(コピーしよう)としたときに出ます。mv src src/sub のように、移動先のパスの途中に元のディレクトリが入っていないかを見ます。cp -r . backup のように「今いる場所を、その中のディレクトリへ」コピーしたときにも、cp: cannot copy a directory, '.', into itself, 'backup/.' と出ました。
Argument list too long(ファイルが多すぎる)
rm *.txt の * はシェルが全部のファイル名に展開してから rm に渡すので、名前の合計が上限(ARG_MAX)を超えると、rm が動く前に失敗します。 20万個のファイルで試しました。ARG_MAX は 2,097,152 バイトで、20万個の名前の合計は区切りの文字を含めて 4,400,000 バイトでした。
$ rm *.txt
bash: /usr/bin/rm: Argument list too long
$ cp *.txt ../nowhere/
bash: /usr/bin/cp: Argument list too long
$ getconf ARG_MAX
2097152
直し方と、20万個を消したときの時間です(tmpfs 上)。
# いちばん速かった方法(-maxdepth 1 で下のディレクトリに入らない)
find . -maxdepth 1 -name '*.txt' -delete
# rm を使う方法(名前に空白があっても安全)
find . -maxdepth 1 -name '*.txt' -print0 | xargs -0 rm
# find だけで rm を呼ぶ方法(0.91秒)
find . -maxdepth 1 -name '*.txt' -exec rm {} +
# ディレクトリごと消してよいなら(0.67秒)
rm -r logs/
cp や mv で同じエラーが出たときは、find . -name '*.txt' -exec cp -t 送り先 {} + のように -t と組み合わせます。関連記事「findコマンドの使い方|目的別逆引き40例と-exec・xargsの違い」で扱っています。
Not a directory(末尾のスラッシュ)
ディレクトリへのシンボリックリンク lnk を mv lnk/ C と書くと、Not a directory で止まりました。末尾の / はリンク先のディレクトリを指すためです。coreutils のマニュアルは、リンクかもしれない移動元に末尾の / を付けないよう注意しています。リンクそのものを移すときは mv lnk C と書きます。
Mac(BSD版)のcp・rm・mvとの違い
Mac の cp・rm・mv は BSD 系で、Linux の GNU 版とオプションが違います。Apple が公開している file_cmds のマニュアルで確かめた違いです。
| 項目 | Linux(GNU coreutils 9.4) | Mac(BSD 系) |
|---|---|---|
cp -R src/ dst の末尾の / |
付けても同じ結果 | 中身だけをコピー |
cp -a の意味 |
-dR --preserve=all |
-RpP |
cp -r |
-R と同じ |
実装によって違うため使わないよう記載 |
--backup・-u・-T・-t・--parents |
ある | 無い |
--update=none などの長いオプション |
ある | 無い |
rm -I |
ある | ある |
/ を消そうとしたとき |
--preserve-root で止める |
/・.・.. の削除はエラー |
mv -h(リンク先をたどらない) |
無い(-T で同じことができる) |
ある |
| 別のディスクへの mv | cp -a 相当でコピーして元を削除 |
cp と rm で行う |
Linux と同じ動きにしたいときは、Homebrew で GNU 版を入れられます。Homebrew の coreutils(2026年10月18日時点で 9.12)は、Mac にある名前と重ならないよう gcp・grm・gmv の名前で入ります。
brew install coreutils
gcp --version
# 元の名前で使うなら(Homebrew の案内より)
PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH"
Windowsのcopy・del・moveとの対応表
Windows のコマンドプロンプトと PowerShell の対応です。Microsoft Learn の各コマンドのページで確かめました。
| Linux | コマンドプロンプト | PowerShell |
|---|---|---|
cp a b |
copy a b |
Copy-Item a b |
cp -r src dst |
xcopy src dst /e /i か robocopy src dst /e |
Copy-Item src dst -Recurse |
mv a b |
move a b |
Move-Item a b |
rm a |
del a |
Remove-Item a |
rm -r dir |
rmdir /s dir |
Remove-Item dir -Recurse |
rm -rf dir |
rmdir /s /q dir |
Remove-Item dir -Recurse -Force |
cp -i(上書き確認) |
copy /-y |
― |
rsync -a --delete src/ dst/ |
robocopy src dst /mir |
― |
copyはサブディレクトリをコピーしません。Microsoft Learn は、サブディレクトリまでコピーするときは xcopy を使うよう書いています。delのページには「del でディスクから消したファイルは取り戻せない」と書かれています。rm と同じく、ごみ箱には入りません。- PowerShell の
cp・mv・rmは、Windows では Copy-Item・Move-Item・Remove-Item の別名です。Linux・Mac の PowerShell では別名にならず、OS の cp・mv・rm が動きます。全部の OS で使える別名はcopy・cpi、move・mi、del・erase・rd・riです。 robocopy /mirは、コピー元に無いファイルをコピー先から消します(/eと/purgeを合わせた動き)。
よくある質問
Q. cp コマンドでディレクトリをコピーするには?
A. cp -r src dst です。時刻や権限も保つなら cp -a を使います。dst が既にあると dst/src の形で1段深く入るので、中身だけなら cp -r src/. dst と書きます。「コピー先があるかどうかで結果が変わる」の節で実例を載せています。
Q. cp コマンドで上書きの確認を出すには?
A. cp -i で上書きの前に確認が出ます。上書きしないなら cp --update=none、上書きされる側を残すなら cp -b です。
Q. rm コマンドでディレクトリを削除するには?
A. 中身ごとなら rm -r ディレクトリ名、空のディレクトリなら rm -d か rmdir です。オプションなしの rm は Is a directory で止まります。
Q. rm -rf で消したファイルは戻せますか?
A. rm にはゴミ箱も取り消しもありません。まだプロセスが開いているファイルだけは、/proc/PID/fd/ からコピーして取り戻せることがあります。「消したファイルが戻らない理由」の節で手順を載せています。
Q. mv コマンドで名前を変更するには?
A. mv 今の名前 新しい名前 です。移動先に同じ名前があると確認なしで上書きするので、心配なら mv -i か mv -b を使います。
Q. mv でディレクトリを移動するには?
A. mv dir 移動先/ で、-r は要りません。移動先に同じ名前の中身のあるディレクトリがあると Directory not empty で止まります。
Q. Argument list too long と出て rm できません。
A. * の展開が上限を超えています。find . -maxdepth 1 -name '*.txt' -delete で消せます。20万個で 0.63 秒でした。
Q. Mac の cp は Linux と違いますか?
A. 違います。Mac の cp -R src/ dst は中身だけをコピーし、Linux では src と同じ結果です。--backup や -u などは Mac の cp にありません。
まとめ
- cp は複製、mv は名前の付け替え、rm は名前の削除。3つとも同じ名前を確認なしで上書き・削除する。
cp -r src dstは dst があると dst/src になる。中身だけならsrc/.か-T。Linux の cp は末尾の/で結果が変わらず、Mac の cp と rsync は変わる。- バックアップは
cp -a。オプションなしの cp は時刻が変わり、リンクは中身に置き換わる。 -nは版と配布元で終了コードが違う。スクリプトでは--update=noneか-bを使う。- rm は unlink で、ゴミ箱も取り消しも無い。戻せる削除にしたいときは trash-cli を使う。
Argument list too longはfind -deleteが最も速かった(20万個で 0.63 秒)。- Permission denied は、ファイルではなく親ディレクトリの書き込み権を見る。
参考・出典
確認日はいずれも 2026年10月18日です。
- GNU coreutils マニュアル「cp invocation」:https://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html
- GNU coreutils マニュアル「mv invocation」:https://www.gnu.org/software/coreutils/manual/html_node/mv-invocation.html
- GNU coreutils マニュアル「rm invocation」:https://www.gnu.org/software/coreutils/manual/html_node/rm-invocation.html
- GNU coreutils マニュアル「Backup options」:https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
- GNU coreutils NEWS:https://github.com/coreutils/coreutils/blob/master/NEWS
- Apple file_cmds(cp.1・rm.1・mv.1):https://github.com/apple-oss-distributions/file_cmds
- Homebrew Formulae「coreutils」:https://formulae.brew.sh/formula/coreutils
- trash-cli(GitHub):https://github.com/andreafrancia/trash-cli
- Microsoft Learn「copy」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/copy
- Microsoft Learn「xcopy」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/xcopy
- Microsoft Learn「robocopy」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
- Microsoft Learn「move」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/move
- Microsoft Learn「del」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/del
- Microsoft Learn「rmdir」:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/rmdir
- Microsoft Learn「Copy-Item」:https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/copy-item
- Microsoft Learn「Move-Item」:https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/move-item
- Microsoft Learn「Remove-Item」:https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/remove-item
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「cp・rm・mvコマンドの使い方|オプション早見表とエラーの直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。