web-dev-qa-db-ja.com

unix mvプログラムはディレクトリに-R(再帰)オプションを必要としませんが、cpはそれを必要とするのはなぜですか?

cpまたはmvを使用する必要がある場合、常にめちゃくちゃになります。「dirを操作するときに-Rオプションが必要ですか?」 GNU coreutils cp-Rを必要とし、mvは必要としません。

cpがdirsをコピーするために-Rオプションを必要とし、mvが必要としない理由を見つけることができません。 cping dirsは-Rなしで(ただし、-Rのように再帰的に動作し、mvのように再帰的に動作しても)、問題を引き起こさないのは、ツール。

説明はありますか?ずっと前に理由があったのでしょうか?


追加の質問:coreutils開発者がデフォルトでcp dirを再帰的にコピーしないのはなぜですか?

59
rslnx

ディレクトリは、(概念的には)名前のリストと、それらの名前が指すiノード番号を含む特別な「ファイル」です。一部の名前はサブディレクトリにすることができます。親ディレクトリを指す特別なエントリ..があります。

したがって、ファイルの名前を変更するのは簡単です。ディレクトリエントリの名前を変更するだけです。これは、ファイルが実際にファイルであるか、別のディレクトリの内容を格納するために使用される「ファイル」であるかを保持します。実際、同じrename syscallは両方を実行します。

ただし、コピーはそれほど簡単な操作ではありません。あなたはcouldディレクトリ「file」をコピーするだけですが、ファイルが同じである2つのディレクトリがあります(それらはハードリンクになります)。ディレクトリへのハードリンクを許可するシステムがあればそれは可能ですが、現代のシステムではそれを許可していないため、少なくとも非ルートに対しては、各サブディレクトリに対してそのコピーを実行する必要があります。 cp -lRを使用すると、実際にcpにこの動作を要求できます。ハードリンクの場合は-l、再帰の場合は-Rです。

しかし、すべてをリンクしたままにすることは、おそらく望んでいることではありません。代わりに、cpで各ファイルをコピーする必要があります。これはかなりコストのかかる操作です。各ファイルをメモリに読み取り、ディスクの2番目の場所に書き戻す必要があります。実際には、ファイルを開いたり、読み込んだり、書き込んだり、閉じたりするには、いくつかのsyscallが必要です。これは、ファイルごとに繰り返す必要があります。

従来のファイルシステムもディスク上でこのように機能します。大量のファイルをコピーする方法はありません。ファイルを個別に調べてコピーする以外に方法はありません。これらは、基本的なコマンドラインユーティリティの設計時に使用されていたファイルシステムの種類です。

45
derobert

別の質問をすることから始めましょう:

cpcp -Rの違いは何ですか?

まあ、-Rフラグがないと、ファイルをコピーすることのみが可能です。これは、誰かがディレクトリを非再帰的にコピーすることを望むのはかなり珍しいためです。非再帰的なコピーは、ディレクトリの2番目の名前になります。直接同じディレクトリ構造に。それが人々が望むことはめったになく、実際にこれを行う別のプログラム(ln)があるため、ディレクトリの非再帰的なコピーは許可されていません。

mvmv -Rの違いは何でしょうか?

mv a bはディレクトリ内の単一のエントリの名前を変更するだけなので、ディレクトリがmvedの場合、その内容も自動的に移動されます。その意味で、mvはすでに再帰的なプロパティ、つまり名前が変更されたディレクトリ内のすべてのエントリの「名前の変更」を提供しています。 a/1からb/1へ。それを行わないmv、つまりディレクトリの名前をaからbに変更しますが、a/1a/1として保持します彼らが何かを動かすことについて言及するときを理解する:食器棚を動かすと、食器棚の内容も動きます。内容なしでディレクトリを移動する他の操作もすでに利用可能で、mkdirと呼ばれています。

21
daniel kullmann

通常、私がUnixロジックにめちゃくちゃになっているときは、Plan9を調べて、Unixの発明者が何年も後に下位互換性にとらわれることなく同じタスクを実装したかを確認します。

したがって、Plan9は、ファイルのみを操作するためのcpおよびmvツールを提供します。

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

ディレクトリをコピーする場合、dircpがあり、これは実際に@{cd fromdir && tar c .} | @{cd todir && tar xT}(rcシェル構文)

ディレクトリを移動する場合、dircp d1 d2 && rm -r d1

cpmvをファイル操作のみに制限する(dirsではなく)というこの決定により、ディスク操作がより明確になり、tarを使用してファイルツリーをコピーすることは理解しやすくなります。とスクリプト。

6
rslnx