この答え は、隠しファイルを含むすべてのファイルをディレクトリsrc
からディレクトリdest
に次のようにコピーできることを示しています。
mkdir dest
cp -r src/. dest
これが実際に機能する理由についての回答やコメントには説明がありません。また、これに関するドキュメントも誰も見つけていないようです。
いくつか試しました。まず、通常のケース:
$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src dest
$ ls -A dest
dest_file src
次に、最後に/.
を付けます。
$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/. dest
$ ls -A dest
dest_file .dotfile src_dir src_file
したがって、これは*
と同様に動作しますが、隠しファイルもコピーします。
$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/* dest
$ ls -A dest
dest_file src_dir src_file
.
および..
は、ディレクトリエントリ自体と同様に、- ここで説明 のように適切なハードリンクです。
この動作はどこから来て、どこに文書化されていますか?
この動作は、文書化されたcp -R
のアルゴリズムの論理的な結果です。 [〜#〜] posix [〜#〜] 、ステップ2fを参照してください:
ディレクトリ内のファイルsource_fileは、ディレクトリdest_fileにコピーされます。 source_filesとしてファイルと共にここにリストされている4つのステップ(1から4)を実行します。
.
と..
は、それぞれ現在のディレクトリと親ディレクトリです。シェルに関する限り、どちらも特別なものではないため、拡張も関係なく、ディレクトリは隠しファイルを含めてコピーされます。一方、*
はファイルのリストに展開され、ここに隠しファイルが除外されます。
src/.
はsrc
内の現在のディレクトリで、src
自体です。 src/src_dir/..
はsrc_dir
の親ディレクトリであり、これもsrc
です。したがって、src
の外部から、src
がディレクトリの場合、cp
のソースファイルとしてsrc/.
またはsrc/src_dir/..
を指定することは同等であり、隠しファイルを含むsrc
の内容。
src/.
を指定するポイントは、src
がディレクトリ(またはディレクトリへのシンボリックリンク)でない場合は失敗しますが、src
はそうでない場合です。また、src
自体はコピーせず、src
の内容のみをコピーします。これもドキュメントと一致します:
targetが存在し、既存のディレクトリに名前を付ける場合、ファイル階層内の各ファイルに対応する宛先パスの名前は、target、targetがスラッシュで終わっていない場合の単一のスラッシュ文字、およびsource_fileを含むディレクトリに対するファイルのパス名。
したがって、cp -R src/. dest
はsrc
の内容をdest/.
にコピーします(ソースファイルはsrc
の.
です)。一方、cp -R src dest
は内容をコピーしますsrc
からdest/src
へ(ソースファイルはsrc
です)。
これを考えるもう1つの方法は、src/src_dir
とsrc
を比較するのではなく、src/.
とsrc/.
のコピーを比較することです。 .
は、前者の場合のsrc_dir
と同じように動作します。
cp -R src/foo dest
を実行すると、dest/foo
を取得します。したがって、ディレクトリdest/foo
が存在しない場合は、cp
によって作成され、src/foo
の内容がdest/foo
にコピーされます。
cp -R src/. dest
を実行すると、cp
はdest/.
が存在することを確認し、src/.
の内容をdest/.
にコピーするだけです。
src
から.
という名前のディレクトリをコピーし、その内容を既存のディレクトリdest/.
とマージすると考えると、理にかなっています。