綾小路龍之介の素人思考

[linux] mv と cp の違い

移動元の inode と移動先のそれが換わらないのが mv、コピー元の inode とコピー先の inode が換わるのが cp。全てのデータは inode によってアクセスできるようになっている。人間のわかりやすさの観点からツリー構造がある。

例えば、以下のようなスクリプトを書いてテストしてみる。cp コマンドの前後でディレクトリの内容がどう変わったかチェックする。

$ cat test.sh
rm -fr src/ dst/

mkdir -p src/
mkdir -p src/fuga
for (( i=0 ; i<3 ; i++ ))
do
        SRC=`printf "src/%03d.txt" $i`
        touch $SRC
        SRC=`printf "src/hoge/%03d" $i`
        mkdir -p $SRC

        for (( j=0 ; j<3 ; j++ ))
        do
                SRC=`printf "src/hoge/%03d/%03d.txt" $i $j`
                touch $SRC
        done
done

mkdir -p dst/
for (( i=0 ; i<2 ; i++ ))
do
        DST=`printf "dst/%03d.txt" $i`
        touch $DST
        DST=`printf "dst/hoge/%03d" $i`
        mkdir -p $DST
        for (( j=0 ; j<2 ; j++ ))
        do
                DST=`printf "dst/hoge/%03d/%03d.txt" $i $j`
                touch $DST
        done
done
ls -Rli
cp -ia src/* dst
#mv -f src/* dst
ls -Rli
exit;

このスクリプトを走らせると以下のような結果が得られる。src 以下のディレクトリとファイルが dst 以下にマージされていることがわかる。このような作業をしたい要望は (僕の場合) 結構頻繁にある。それは、ポータブルメモリで文書ツリーを持ち歩いて、その内容を編集後、再度コピー元にマージする場合だ。

$ sh test.sh
.:
total 12
36210484 drwxr-xr-x 3 hoge hoge 4096 2010-06-05 09:36 dst
36210478 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 09:36 src
18972715 -rw-r--r-- 1 hoge hoge  566 2010-06-05 09:36 test.sh

./dst:
total 4
19054768 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 000.txt
19054769 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 001.txt
36210485 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 09:36 hoge

./dst/hoge:
total 8
36210486 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 000
36210487 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 001

./dst/hoge/000:
total 0
19087531 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19087532 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt

./dst/hoge/001:
total 0
19103774 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19103775 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt

./src:
total 8
18956416 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 000.txt
18956417 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 001.txt
18956418 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 002.txt
36210479 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 fuga
36210480 drwxr-xr-x 5 hoge hoge 4096 2010-06-05 09:36 hoge

./src/fuga:
total 0

./src/hoge:
total 12
36210481 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 000
36210482 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 001
36210483 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 002

./src/hoge/000:
total 0
19005474 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19005475 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19005476 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./src/hoge/001:
total 0
19021931 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19021932 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19021933 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./src/hoge/002:
total 0
19038217 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19038218 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19038219 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt
cp: overwrite `dst/000.txt'? y
cp: overwrite `dst/001.txt'? y
cp: overwrite `dst/hoge/000/001.txt'? y
cp: overwrite `dst/hoge/000/000.txt'? y
cp: overwrite `dst/hoge/001/001.txt'? y
cp: overwrite `dst/hoge/001/000.txt'? y
.:
total 12
36210484 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 09:36 dst
36210478 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 09:36 src
18972715 -rw-r--r-- 1 hoge hoge  566 2010-06-05 09:36 test.sh

./dst:
total 8
19054768 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 000.txt
19054769 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 001.txt
19054770 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 002.txt
36210488 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 fuga
36210485 drwxr-xr-x 5 hoge hoge 4096 2010-06-05 09:36 hoge

./dst/fuga:
total 0

./dst/hoge:
total 12
36210486 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 000
36210487 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 001
36210489 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 002

./dst/hoge/000:
total 0
19087531 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19087532 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19087533 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./dst/hoge/001:
total 0
19103774 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19103775 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19103776 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./dst/hoge/002:
total 0
19136568 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19136566 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19136567 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./src:
total 8
18956416 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 000.txt
18956417 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 001.txt
18956418 -rw-r--r-- 1 hoge hoge    0 2010-06-05 09:36 002.txt
36210479 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 fuga
36210480 drwxr-xr-x 5 hoge hoge 4096 2010-06-05 09:36 hoge

./src/fuga:
total 0

./src/hoge:
total 12
36210481 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 000
36210482 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 001
36210483 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 09:36 002

./src/hoge/000:
total 0
19005474 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19005475 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19005476 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./src/hoge/001:
total 0
19021931 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19021932 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19021933 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

./src/hoge/002:
total 0
19038217 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 000.txt
19038218 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 001.txt
19038219 -rw-r--r-- 1 hoge hoge 0 2010-06-05 09:36 002.txt

コピー先に同じパスが無かったファイルやディレクトリについては、コピー元と内容が同じで新しい inode 番号が割り振られた別のファイルが出来ている。コピー先に同じパスが有ったファイルやディレクトリについては、コピー元と内容が同じでコピー先と同じ inode 番号のファイルに内容を上書きされている。

cp 前後の Inode 変化
cp 前 inodecp 後 inodeパス
3621048436210484./dst/
3621047836210478./src/
1897271518972715./test.sh
1905476819054768./dst/000.txt
1905476919054769./dst/001.txt
-19054770./dst/002.txt
-36210488./dst/fuga/
3621048536210485./dst/hoge/
3621048636210486./dst/hoge/000/
3621048736210487./dst/hoge/001/
-36210489./dst/hoge/002/
1908753119087531./dst/hoge/000/000.txt
1908753219087532./dst/hoge/000/001.txt
-19087533./dst/hoge/000/002.txt
1910377419103774./dst/hoge/001/000.txt
1910377519103775./dst/hoge/001/001.txt
-19103776./dst/hoge/001/002.txt
-19136568./dst/hoge/002/000.txt
-19136566./dst/hoge/002/001.txt
-19136567./dst/hoge/002/002.txt
1895641618956416./src/000.txt
1895641718956417./src/001.txt
1895641818956418./src/002.txt
3621047936210479./src/fuga/
3621048036210480./src/hoge/
3621048136210481./src/hoge/000/
3621048236210482./src/hoge/001/
3621048336210483./src/hoge/002/
1900547419005474./src/hoge/000/000.txt
1900547519005475./src/hoge/000/001.txt
1900547619005476./src/hoge/000/002.txt
1902193119021931./src/hoge/001/000.txt
1902193219021932./src/hoge/001/001.txt
1902193319021933./src/hoge/001/002.txt
1903821719038217./src/hoge/002/000.txt
1903821819038218./src/hoge/002/001.txt
1903821919038219./src/hoge/002/002.txt

ファイルをコピーするのではなく、移動したい場合もあるだろう。cp と同じことを mv でやろうとした場合、以下のように書き換えてみる。"mv: cannot move `src/hoge' to `dst/hoge': Directory not empty" と怒られる。重要な示唆は、mv の場合 inode が変更されない、cp の場合 inode は変更されるという点だ。つまり、移動先に移動元と同じ名前のファイルやディテクトリがあったとき、mv の場合は移動元の inode に紐付けられたファイルやディレクトリのパスを移動先に変更する、cp の場合は移動元の inode に紐付けられたファイルやディレクトリと同じ内容のファイルやディレクトリを移動先に新規作成 (新しい inode が割り振られる) する。ファイルやディレクトリの相対パスが同じになる場合、mv では移動先のファイルをどう扱うかわからないので、エラーを出す。移動先のファイルを削除する場合は、-f を使えばいいが、ファイルの入っているディレクトリに対しては効果なし。そんなわけで、cp を使って inode は違うけど、内容は同じファイルやディレクトリを作って、その後に移動元を削除するほうがわかりやすい(と思う)。

$ sh test.sh
.:
total 12
36210484 drwxr-xr-x 3 hoge hoge 4096 2010-06-05 10:09 dst
36210478 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 10:09 src
18972715 -rw-r--r-- 1 hoge hoge  566 2010-06-05 10:09 test.sh

./dst:
total 4
19054768 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 000.txt
19054769 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 001.txt
36210485 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 10:09 hoge

./dst/hoge:
total 8
36210486 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 000
36210487 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 001

./dst/hoge/000:
total 0
19087531 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19087532 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt

./dst/hoge/001:
total 0
19103774 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19103775 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt

./src:
total 8
18956416 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 000.txt
18956417 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 001.txt
18956418 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 002.txt
36210479 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 fuga
36210480 drwxr-xr-x 5 hoge hoge 4096 2010-06-05 10:09 hoge

./src/fuga:
total 0

./src/hoge:
total 12
36210481 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 000
36210482 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 001
36210483 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 002

./src/hoge/000:
total 0
19005474 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19005475 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19005476 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt

./src/hoge/001:
total 0
19021931 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19021932 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19021933 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt

./src/hoge/002:
total 0
19038217 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19038218 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19038219 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt
mv: overwrite `dst/000.txt'? y
mv: overwrite `dst/001.txt'? y
mv: overwrite `dst/hoge'? y
mv: cannot move `src/hoge' to `dst/hoge': Directory not empty
.:
total 12
36210484 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 10:09 dst
36210478 drwxr-xr-x 3 hoge hoge 4096 2010-06-05 10:09 src
18972715 -rw-r--r-- 1 hoge hoge  566 2010-06-05 10:09 test.sh

./dst:
total 8
18956416 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 000.txt
18956417 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 001.txt
18956418 -rw-r--r-- 1 hoge hoge    0 2010-06-05 10:09 002.txt
36210479 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 fuga
36210485 drwxr-xr-x 4 hoge hoge 4096 2010-06-05 10:09 hoge

./dst/fuga:
total 0

./dst/hoge:
total 8
36210486 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 000
36210487 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 001

./dst/hoge/000:
total 0
19087531 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19087532 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt

./dst/hoge/001:
total 0
19103774 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19103775 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt

./src:
total 4
36210480 drwxr-xr-x 5 hoge hoge 4096 2010-06-05 10:09 hoge

./src/hoge:
total 12
36210481 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 000
36210482 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 001
36210483 drwxr-xr-x 2 hoge hoge 4096 2010-06-05 10:09 002

./src/hoge/000:
total 0
19005474 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19005475 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19005476 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt

./src/hoge/001:
total 0
19021931 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19021932 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19021933 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt

./src/hoge/002:
total 0
19038217 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 000.txt
19038218 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 001.txt
19038219 -rw-r--r-- 1 hoge hoge 0 2010-06-05 10:09 002.txt

移動先に同じパスが無かったファイルやディレクトリについては、移動元と内容が同じで同じ inode 番号が割り振られた同じファイルが移動先に移動された。移動先に同じパスが有ったファイルやディレクトリについても、移動元と内容が同じで移動元と同じ inode 番号のファイルが移動されてきている。

cp 前後の Inode 変化
cp 前 inodecp 後 inodeパス
3621048436210484./dst/
3621047836210478./src/
1897271518972715./test.sh
1905476818956416./dst/000.txt
1905476918956417./dst/001.txt
-18956418./dst/002.txt
-36210479./dst/fuga/
3621048536210485./dst/hoge/
3621048636210486./dst/hoge/000/
3621048736210487./dst/hoge/001/
1908753119087531./dst/hoge/000/000.txt
1908753219087532./dst/hoge/000/001.txt
1910377419103774./dst/hoge/001/000.txt
1910377519103775./dst/hoge/001/001.txt
18956416-./src/000.txt
18956417-./src/001.txt
18956418-./src/002.txt
36210479-./src/fuga/
3621048036210480./src/hoge/
3621048136210481./src/hoge/000/
3621048236210482./src/hoge/001/
3621048336210483./src/hoge/002/
1900547419005474./src/hoge/000/000.txt
1900547519005475./src/hoge/000/001.txt
1900547619005476./src/hoge/000/002.txt
1902193119021931./src/hoge/001/000.txt
1902193219021932./src/hoge/001/001.txt
1902193319021933./src/hoge/001/002.txt
1903821719038217./src/hoge/002/000.txt
1903821819038218./src/hoge/002/001.txt
1903821919038219./src/hoge/002/002.txt

リファレンス

  1. Manpage of MV
  2. mv manpage - Google 検索
  3. [Linux] cp /dev/null logfile を使う理由 - 百舌日記
  4. mv cp inode - Google 検索
  5. LPICレベル1に挑戦(7) | blog.paz-para.com
  6. Linux: Cannot move folders – inter-device move failed, unable to remove target: Is a directory | Ali Aboosaidi
  7. inter-device move failed - Google 検索

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2009-06-01T10:50:16+09:00
  2. Modified: 2009-06-01T10:50:16+09:00
  3. Generated: 2017-10-04T23:09:18+09:00