私の質問は-r
、ディレクトリのコピーを作成するときに(再帰)フラグを使用する必要があるのはなぜですか?すなわち、なぜこれを行うのですか:
$ cp -r dir1 copyDir1
ディレクトリをコピーするときにこの動作が望ましくない場合
ディレクトリの再帰的なコピーは、実際には「デフォルト」の動作ではありません。私たちが常に望んでいる行動は?
これは余分なフラグのように感じます。
私の質問は-r
、ディレクトリのコピーを作成するときに(再帰)フラグを使用する必要があるのはなぜですか?すなわち、なぜこれを行うのですか:
$ cp -r dir1 copyDir1
ディレクトリをコピーするときにこの動作が望ましくない場合
ディレクトリの再帰的なコピーは、実際には「デフォルト」の動作ではありません。私たちが常に望んでいる行動は?
これは余分なフラグのように感じます。
回答:
ファイルシステムの動作方法では、ディレクトリは実際にはファイルを含むフォルダではなく、ディレクトリはそれに接続された「子」ファイルへのiノードポインタを含むファイルです。つまり、ファイルシステムの観点では、ファイルはファイルですが、ディレクトリは接続されたファイルのリストを含む単なるファイルです。
コマンドラインの観点から、これを行う:
$ cp dir1 copyDir1
基本的には、という名前のファイルをという名前dir1
の新しいファイルにコピーすることを意味しますcopyDir1
。そして、ファイルシステムに関する限り、dir1
とにかく単なるファイルです。それが「ディレクトリ」であるという事実は、ファイルシステムが実際にdir1
そのビットの山が実際に何であるかを確認するときにのみ明らかになります。
この-r
フラグは、ファイル/ディレクトリツリーを再帰的にロールダウンし、そのファイルの「子」である可能性のあるすべてのコンテンツを新しい場所にコピーするようにファイルシステムに指示します。
なぜそれが不必要または冗長に見えるのかについて、これはファイルシステムを扱う歴史的な方法に本当に帰着します。すべてのタイプのユーザー関連エラーから安全なシステムを作成します。偶発的および意図的。
つまり~/bin
、ホームディレクトリにコピーしたいファイルがありますが、誤って(~
あなたは人間であり、間違いを犯しているため)除外してしまったとします/bin
。
cp /bin/ ~/copy_of_bin
/bin
ディレクトリであるという「セーフティネット」と-r
フラグの必要性を組み合わせることで、現在のシステムのバイナリルート全体を誤ってホームディレクトリにコピーすることを回避できます。そのセーフティネットが存在しなかった場合、マイナーな、またはおそらくメジャーな災害が起こります。
ここでのロジックは、ユーザーがシステムを破壊する可能性のある災難をユーザーが作成しないように、GUI以前(グラフィカルユーザーインターフェイス)の論理/動作規則を設定する必要があるということです。そして、-r
フラグを使用することはそれらの1つです。
それが不要に思える場合は、Linuxファイルシステムの上に配置できる最新のGUIシステムを探す必要があります。GUIは、ファイルやディレクトリを簡単にドラッグアンドドロップできるようにすることで、このような基本的なユーザーの問題に対処します。
しかし、テキストベースのインターフェイスの領域の場合、その世界の多くの「ユーザーエクスペリエンス」は、基本的に論理的で色相ベースの道路バンプであり、潜在的な災害を回避できるようにユーザーをチェックし続けます。
同様に、これがデフォルトでLinux / Unixファイルシステムに777
パーミッションとsudo
権限が設定されていない理由と、ユーザーが777
パーミッションを設定したり、全員にsudo
権限を付与したときに実際のシステム管理者が勝つ方法です。これらは、システムを安定させ、可能な限り「ユーザーの証拠」とするために行う基本的なことです。それらの慣習を短絡しようと急ぐ人は、それを知らずにシステムに損害を与える可能性が高いでしょう。
追加情報: Unix Stack Exchangeサイトの別の回答では、ディレクトリの非再帰的コピーに問題がある理由を説明しています。強調は私のものです。
-Rフラグがなければ、ファイルをコピーすることしかできません。誰かがディレクトリを非再帰的にコピーするのはかなり珍しいからです。非再帰的なコピーは、ディレクトリの2番目の名前になり、直接同じディレクトリ構造。 人々が望むものはめったにないので、実際にこれを行う別のプログラム(ln)があるため、ディレクトリの非再帰的コピーは許可されていません。
したがって、ディレクトリが実際に内部にiノードアイテムを含むファイルである場合、そのファイルのストレートコピーを作成することは、ハードリンクがどのように機能するかに相当します。誰もが望んでいるものではありません。
cp -r /bin
ましたcp-r ~/bin
。フラグ自体は、間違いを防いだり、注意を払うことを必ずしも上手くしたりするものではありません。間違いを防ぎたい場合は、cpコマンドで問題のノードを簡単に確認し、「これはディレクトリです。すべてのコンテンツを指定した場所にコピーしますか? / n)?」 それがセーフティネットになります。ディレクトリに-rを要求すると、コードの膨張が何よりも抑えられます。
これがほぼ常に必要な動作であることは非常に真実です。ただし、これは必ずしも再帰的にコピーすることがデフォルトの動作であることを意味するわけではありません。
Unix哲学にルーツがあるように理由はcp
作用すると思う。Unixは、インターフェースと実装の両方で単純なプログラム(さらに悪いと呼ばれることが良い)だけでなく、1つのことを行い、それをうまく行うプログラムを好みます。
ここでのパズルの重要な部分は、cp
ディレクトリをコピーしないcp
こと、つまりファイル(およびファイルのみ)をコピーしないことを認識することです。ディレクトリをコピーする場合、各ディレクトリのファイルをコピーするために、cp
自分自身を再帰的に呼び出します。
もちろん、「ディレクトリのコピー」と「ファイルの再帰的なコピー」の違いは、ユーザーの観点からは絶対に何もありませんが、このインターフェイスを使用すると、実装が簡単になります。
cp
ディレクトリをコピーできるようにした場合、ディレクトリでのみ意味のある機能を追加するようになります。たとえば、で終わるファイル名のみをコピーしたい場合があります.sh
。必然的に、これは私たちが他のオペレーティングシステムで慣れている肥大化と機能のクリープにつながり、ソフトウェアが遅くなり、複雑で、エラーが発生しやすくなります。
別の利点は-r
、ユーザーがインターフェイスの下で実際に何が起こっているのかを理解するのにも役立つということです。これの良い副作用は、再帰操作の概念を学習すると、それをサポートする他のツール(grep
例えば、)
一部の人々は、実装の詳細をユーザーに公開することは悪いことであり、より多くの機能を備えていることは良いことだと確実に言うでしょう。ここでの私の意図は、単にこの振る舞いの理論的根拠を説明するだけなので、どちらの方法でも議論しようとはしません。
ディレクトリとのやり取りにより、1つのファイルだけでなく、ディレクトリとやり取りしていることがわかります。
例えば:
$ tree
.
└── folder1
└── sub1
└── subsub1
3 directories, 0 files
$
$ cp folder1/ folder2
cp: folder1/ is a directory (not copied).
$
$ mkdir blah
$ cp blah/ blah2
cp: blah/ is a directory (not copied).
$ rm blah/
rm: blah/: is a directory
したがって、フォルダを正常にコピーしたい場合、フォルダとフォルダの参照に関連するオブジェクトの両方を意味するため、ファイルのコレクションのように扱う必要があります。
$ cp -r folder1/ folder2
$ rm -rf folder1
デフォルトを変更すると、数千のシェルスクリプトが破損します。これは、よく知られているデフォルトの動作に対するPOSIXおよびSUS要件につながります。
その理由は、さまざまなUNIXブランチでのcp、ln、およびmvコマンド(ほとんどの古いUNIXシステムではすべて同じバイナリ)の歴史的な発展です。場合には-r
(早期登場cp
ディレクトリをコピーするオプションがありませんでした。ここでは、早期のcpのmanページがあるなし-r
か-R
)、特殊ファイル、シンボリックリンクやファイルシステムや他の気まぐれを扱う上での様々な違いがありました。
この標準の以前のバージョンには、ファイル階層をコピーする-rオプションのサポートが含まれていました。-rオプションは、BSDおよびBSD派生システムでの歴史的な慣習です。このオプションはPOSIX.1-2008では指定されなくなりましたが、一部の実装では存在する場合があります。-Rオプションは、-rオプションに近い同義語として追加されました。これは、再帰的なディレクトリ降下を行うPOSIX.1-2008のこのボリュームの他のすべてのオプションとの一貫性のために選択されました。
-Rと削除された-rオプションの違いは、レギュラーおよびディレクトリ以外のファイルタイプのcpによる処理にあります。-オプションが特別なファイルをどのように処理して、歴史的な実装と、POSIX.1-2008のこのボリュームで定義された-Rと同じ機能を持つ-rのサポートを選択したものの両方を許可するかは、実装定義でした。歴史的な理由から、元の-rフラグは、通常のファイルとは異なる特殊ファイルを処理しませんでしたが、常にファイルを読み取り、その内容をコピーしました。これには、特殊なファイルタイプが存在する場合に明らかな問題がありました。たとえば、キャラクターデバイス、FIFO、およびソケット。
実際、あなたはまだいくつかの人々が定期的に使用しているのを見るでしょう:
cd dir1 ; tar -cf - . | (cd dir2 ; tar -xpf -)
彼らは、そのcp -r
実装が任意のマシンで使用されているものであると信じていないためです。または彼らがtar
行動を望んでいるからです。
このフラグが必要なのcp
は、ディレクトリだけでなく、ファイルとディレクトリをコピーするコマンドである場合のみです。
ディレクトリのコピー用の特別なコマンドがあった場合、「デフォルト」の動作は確実に再帰コピーになります。
mkdir
ですか?
他の人が言及したように、ディレクトリは基本的には通常のファイルとは対照的に別の種類のファイルであり、通常は他のファイルを「含む」(指す)。同じことが適用されるサブディレクトリを含めることができます...
したがって、ディレクトリをコピーする場合(ユーザーの観点)、実際には多数のファイル(ファイルシステムの観点)(通常のファイル、ディレクトリファイル、シンボリックリンクなど)をコピーし、すべてのディレクトリファイルに対して、それを再帰的に繰り返します。処理する。定義上、ディレクトリのコピーは再帰的なプロセスであるため、cpの引数はと呼ばれ--recursive
ます。
もちろん、ユーザー環境でコマンドショートカットを作成するのは非常に簡単です(これを.profile / .bashrcファイルに入れて、永続的に使用できるようにします)。
alias cpr='cp -r'
または多分良い:
alias cpa='cp -av'
そうすれば、を使用cpa dir1 copyDir1
してディレクトリをコピーでき、コピー対象を印刷するだけでなく、ファイルのアクセス許可も適用します。
そして、cpは理論的にソースファイルがディレクトリであることを検出し、それを再帰的にコピーするかどうかを尋ねることができると述べたので、ここに簡単な提案があります:
cp()
{
if [ ! -e "$1" ]; then
echo missing source file
return 1
fi
arg="-d --preserve=all -v"
if [ -d "$1" ]; then
read -p "Copy directory recursively? " -n 1 -r
if [ "$REPLY" == "y" ]; then
arg="$arg -r"
fi
echo
fi
/usr/bin/cp $arg "$@"
}
これは単なる安価なcpラッパーです。常にすべてのメタデータを保存します(つまり、ファイルの変更時間をコピーし、シンボリックリンクを適切にコピーするなど)。ディレクトリをコピーしようとする場合、(再帰的に)コピーするかどうかを尋ねます。