cp --no-target-directoryの説明


10

質問:の簡単な使用例が必要cp --no-target-directoryです。

理解するのが難しいcp --no-target-directoryです。の説明mv --no-target-directoryはわかりますが、の使い方を想像することはできませんcp

たとえば、コマンドmv /tmp/source /tmp/destが成功した場合、/tmp/source名前が変更されたという保証はありません。他のプロセスがディレクトリとして作成された場合/tmp/dest/tmp/dest/source代わりに名前が変更された可能性があります/tmp/dest。ただし、mv -T /tmp/source /tmp/dest成功した場合、/tmp/source was renamed to/ tmp / dest` は問題ありません。(ソース

回答:


15

デフォルトでcpは、最後の引数が既存のディレクトリかどうかをテストします。これが発生した場合cp、ソースのベース名を使用して、そのディレクトリ内にリンクを作成します。つまり、コマンド

cp foo/bar wibble

場合はwibble、次に既存のディレクトリでcpコピーするソースがwibble/barwibbleが存在しない場合はcp、ソースをにリンクしますwibble

コピーが常にwibbleであることを確認したい場合は、--no-target-directory(エイリアス-T)オプションを指定できます。そうすれば、cp成功した場合、コピーが確実に呼び出されwibbleます。wibbleディレクトリとしてすでに存在する場合、cp失敗します。

表形式で:

The target is …             Without -T               With -T
existing directory          copy in the directory    error
existing file (not dir)     overwrite                overwrite
does not exist              create                   create

唯一の違いは-T、では、ターゲットが既存のディレクトリの場合、コマンドがエラーを返すことです。これは、ディレクトリが存在しないことが予想される場合に役立ちます。予期しないことが発生する代わりに、エラーメッセージが表示されます。

同じことが、にも適用されるmvln。ターゲットがのある既存のディレクトリである場合-T、それらは暗黙のうちに別のことをするのではなく、エラーを通知します。

ではcp、別のケースがあります。再帰的なコピーを行い、ソースがディレクトリのcp -T場合、ソース自体をコピーするのではなく、ソースのコンテンツを宛先にコピーします。つまり、

$ tree source destination 
source
└── foo
destination
└── bar

その後

$ cp -rv source destination
`source' -> `destination/source'
`source/foo' -> `destination/source/foo'

一方

% cp -rvT source destination
`source/foo' -> `destination/foo'

8

あなたは使用することになり--no-target-directoryますが、コピーされたソースディレクトリたくない場合は下にコピーしたソースディレクトリたい、既存の宛先ディレクトリを上に先ディレクトリを。

以下に、ディレクトリコピーの例を示します--no-target-directory

$ mkdir a
$ touch a/b a/c
$ find
.
./a
./a/c
./a/b
$ cp -r a b       # b does not exist; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r a b       # b already exists; a is copied *underneath* it
$ find
.
./b
./b/a
./b/a/b
./b/a/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r --no-target-directory a b     # b already exists; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b

次のように、ソースディレクトリ名にスラッシュドット/.を付けることで同じ効果を得ることができます。これにより、ソースディレクトリがのではなく上にcp -r a/. bコピーa され ますb b

上記の方法はどちらも、「ソースディレクトリの内容のみを既存の宛先にコピーする」と同じではありません。時間と権限を保持するように要求すると、既存の宛先ディレクトリがソースディレクトリの時間と権限を取得するためです。例(不要な情報を削除するために編集):

$ find . -ls
drwx------   Oct 13 13:31 ./b         # note date and permissions
drwxr-xr-x   Jan  1  2013 ./a         # note date and permissions
-rw-r--r--   Oct 13 13:23 ./a/c
-rw-r--r--   Oct 13 13:23 ./a/b
$ cp -rp --no-target-directory a b    # preserve mode and timestamps
$ find . -ls
drwxr-xr-x   Jan  1  2013 ./b         # note copied date and permissions
-rw-r--r--   Oct 13 13:23 ./b/b
-rw-r--r--   Oct 13 13:23 ./b/c
drwxr-xr-x   Jan  1  2013 ./a
-rw-r--r--   Oct 13 13:23 ./a/c
-rw-r--r--   Oct 13 13:23 ./a/b

コンテンツのみのコピーは、ソースディレクトリのモードまたはタイムスタンプを宛先ディレクトリに転送しません。


2

次はどうですか?

$ cp -rvT Dir_1 Dir_2
‘Dir_1/File_3.txt’ -> ‘Dir_2/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/File_2.txt’
$ cp -rv Dir_1 Dir_2
‘Dir_1’ -> ‘Dir_2/Dir_1’
‘Dir_1/File_3.txt’ -> ‘Dir_2/Dir_1/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/Dir_1/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/Dir_1/File_2.txt’

そのため、これは書き方が異なるだけcp Dir_1/* Dir_2/です。ただし、Dir_1のルートにある隠しファイルをキャッチしますcp *。これは、単純なでは見逃されます。

$ touch Dir_1/.Hidden_File_{1,2,3}.txt
$ cp -rv Dir_1/* Dir_2
cp: No match.
$ cp -rvT Dir_1 Dir_2
‘Dir_1/.Hidden_File_2.txt’ -> ‘Dir_2/.Hidden_File_2.txt’
‘Dir_1/.Hidden_File_3.txt’ -> ‘Dir_2/.Hidden_File_3.txt’
‘Dir_1/.Hidden_File_1.txt’ -> ‘Dir_2/.Hidden_File_1.txt’

[out] --no-target-directoryオプションで機能します。--recursiveを使用している限り、すべてが問題ありません([ coreutils 8.12GNU / Linuxで]を使用)。主な違いは--no-target-directory、コンテンツではなくディレクトリ自体がコピーされることです[研究はまだ進行中]
erch
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.