

シェルでファイルを別のディレクトリに移動したいです。  
mvをして何らかの原因で失敗した場合、データ損失の可能性がありますか？

一般的な業務レベルの方法として、ファイル移動をして、ファイル移動が成功したことの確認方法も教えていただけますと幸甚です。


CC BY-SA 4.0
2019-10-30T03:36:54.573
60106
2019-11-15T09:28:37.313
2019-10-30T10:03:35.807
36122
36122
question
linux sh
mvコマンド失敗により損失は起こりうる？


データ損失を定義しないと話がかみ合わないでしょう。例えば

[code]

    $ mv filea backup/filea
    
[/code]

であっても、既にある `backup/filea` は削除され失われます。これはデータ損失でしょうか、そうではないのでしょうか？

意図したファイルの削除は除き、ファイル内容が変化するか否かだけ考えるとして

１．同一ファイルへの `mv` は事前に検出され何も起きません。つまり損失なしです。ンなアホなことしないと思いこみがちですが symlink
があると気付かずに同一ファイルへの `mv` になってしまうことはまれによくあります。

[code]

    $ mv fileb .
    $ mv filec <symlink-to-this-directory>/filec
    同一ファイルの指摘がなされてエラー
    
[/code]

２．ディレクトリ構造を矛盾させる `mv` は事前に検出され以下略。

[code]

    $ mkdir hoge
    $ mkdir hoge/piyo
    $ mv hoge hoge/piyo
    ディレクトリのサブディレクトリへの移動はエラー
    
[/code]

３．同一ディスク装置内で使われる場合 `inode`
とファイル名の対応（のことをディレクトリエントリと呼びます）が変わるだけでファイル本体にはノータッチなので、データ損失はないと考えていいです。

[code]

    $ mv filed filee
    同一ディレクトリ内移動は同一装置内と思われるので損失なしに成功
    
[/code]

４．同一マシン内の別ディスク装置に移動させる場合はファイル本体のコピーが入ります。容量不足等があったらコピー中に失敗し元ファイルは消さないので損失なし。

[code]

    $ mv filef /mounted_other_drive/fileg
    
[/code]

５．異マシン・異構造のファイルシステムへの移動は同上。ただしマウント先に機能が無い情報は失われます。例えばスパースファイルをスパース機能のないマウント先に
`mv` するとサイズが爆発するでしょう（未テスト）。

コピー中に、ディスク装置の故障でデータ化けするとかは考慮してません ( `mv` 固有の話ではないため) `GNU coreutils` 中の `mv` や
`cp` のデータコピー部ソース `copy.c` をちょろっと見た範囲では、コピー元と先でファイル内容の CRC
値を比較するなどの挙動はしていないです（ハードウエアレベルで化けない前提でコード書かれています）。ネットワーク上のデータ化けは TCP
レベルで訂正されるので問題ないです。


CC BY-SA 4.0
2019-10-30T05:02:36.073
60112
2019-10-30T07:02:03.763
2019-10-30T07:02:03.763
8589
8589
60106
answer


もし、`mv`コマンドの実行にリスクがあると感じられる場合は、`-i`オプションや`-n`オプション
(`-nv`のほうが良い)を活用されると良いと思います。

<https://eng-entrance.com/linux_command_mv>

例えば `mv -i a.txt b.txt` を実行すると、`b.txt`がすでに存在していたときに、上書き確認メッセージが出ますし、`mv -nv
a.txt b.txt`を実行すると、`b.txt`がすでに存在していたときは上書きしません。

質問の意図に合う使い方では、`mv -i`が良いかもしれませんね。

また、意図せずファイルを上書きすることを避けたい場合などには、これに加えて、`git`や`rsync`等を活用したファイルのバックアップをおすすめします。


CC BY-SA 4.0
2019-10-30T15:17:37.723
60143
2019-10-30T15:17:37.723
17181
60106
answer


`mv` は、同一ファイルシステムか、そうでないかで動作が変わります。

`mv /src/file /dst/file` を実行した場合、 `/src/` と `/dst/` が、同一ファイルシステムの場合は
`rename()` システムコールが利用されます。`rename()` はディレクトリエントリが書き換わるだけなので、`/dst/file`
のデータが失われることはないと思います。

ファイルシステムをまたがる場合は、次の動作をします。

  1. `/src/file` を `/dst/file` にコピー
  2. `/src/file` を削除

上記1. の途中で `kill` されたりすると、`/dst/file` が中途半端にコピーされた状態になる可能性があります。回避するには
同一ファイルシステム内にコピーしてから、`mv` することで、 `rename()` システムコールが使われるようにします。

[code]

    cp /src/file /dst/temporary
    mv /dst/temporary /dst/file  ←同一ファイルシステム内の mv なので安全
    rm /src/file
    
[/code]


CC BY-SA 4.0
2019-11-15T09:28:37.313
60554
2019-11-15T09:28:37.313
5008
60106
answer