内部に別のディレクトリを作成する代わりに「cp」にディレクトリを上書きさせる方法は?


107

既存のディレクトリを上書きするBashスクリプトを記述しようとしています。ディレクトリがfoo/あり、それで上書きしようとしbar/ています。しかし、私がこれをするとき:

cp -Rf foo/ bar/

新しいbar/foo/ディレクトリが作成されます。それは欲しくない。には2つのファイルがありますfoo/ab。同じ名前のファイルbar/もあります。私が欲しいfoo/afoo/b交換するbar/abar/b

回答:


122

これは、の-Tオプションを使用して行うことができますcp
のマニュアルページを参照してくださいcp

-T, --no-target-directory
    treat DEST as a normal file

したがって、例に従って、以下はファイル構造です。

$ tree test
test
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

-vVerboseに使用すると、明確な違いがわかります。オプション
だけを使用する-R場合。

$ cp -Rv foo/ bar/
`foo/' -> `bar/foo'
`foo/b' -> `bar/foo/b'
`foo/a' -> `bar/foo/a'
 $ tree
 |-- bar
 |   |-- a
 |   |-- b
 |   `-- foo
 |       |-- a
 |       `-- b
 `-- foo
     |-- a
     `-- b
3 directories, 6 files

このオプションを使用する-Tと、内容が上書きされ、宛先はディレクトリではなく通常のファイルのよう扱われます

$ cp -TRv foo/ bar/
`foo/b' -> `bar/b'
`foo/a' -> `bar/a'

$ tree
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

これで問題が解決するはずです。


22
誰もがこれでアップトリップするだけの場合には、それはOSX CPで動作しませんdeveloper.apple.com/library/mac/documentation/Darwin/Reference/...
dnfehren

9
上記の例は問題を覆い隠していますが、この答えがOPが探しているものであることは明らかではありません... -Tオプションを指定すると、既存のターゲット(bar/)にあるがソース()にないファイルはfoo/残りますそのため、これはほとんどの人がディレクトリの完全な上書きを検討するものではありません。すなわち。場合はbar/baz、すでに存在していた、それはまだ...その後に存在するであろう
ロボ

1
この回答はopの質問には答えますが、宛先がすでに存在し、そこに含まれているコンテンツを削除したいがソースディレクトリには存在しない場合のケースには対応していません。これは、ある場所から別の場所にファイルをコピーする場合の予想される動作ではありません。ソース内にも存在するターゲットのものを上書きするだけで、ソース内にないターゲット内の何も変更しません。あなたはそれを行うためのコマンドを付加することで、ターゲットフォルダをきれいにすることができます:rm -rf bar/* && cp -TRv foo/ bar/
theferrit32

1
私はマインドリーダーではありません... OPが何を求めていたのか、それ以上の説明はありませんが、これは間違いなく私(MEEEE)が求めていた答えでした
Assimilater

2
誰が最もupvotedコメント内のリンクが機能しない理由でアップトリップするだけの場合には、ここにある:web.archive.org/web/20170909193852/https://developer.apple.com/...
硫黄

48

2つのステップで実行します。

rm -r bar/
cp -r foo/ bar/

11
これは実際にこれまでに示した唯一のbarであり、コンテンツがと同じであることを保証します。のアイテムとに既に存在している可能性のある他のアイテムのfoo組み合わせではありません。以下の@Saurabh Meshramからの非常に賛成の回答にはこの問題があります。foobar
robo 2016

1
非表示のファイルも含め、すべてのファイルがバーから削除されるため、これを使用する場合は特に注意してください。
エリアグラディ2017

mac osx: rm -rf bar/; cp -r foo/ !$
Michael Dimmitt 2017

1
これは、常に実行可能であるとは限りません...または望ましい... 大規模なディレクトリであるかどうかfooを想像してくださいbar...中には、削除したくないというファイルが含まれbarていない可能性がありますfoo。これは現実的な答えとは見なされませんimho
Assimilater

私にとってはうまくいきましたが、foo /に含まれているがbar /には含まれていない可能性があるため、これを実行すると削除されるため、最善の解決策ではありません。
Nitwit

46

bar/最終的にと同じになるようにしたい場合はfoo/rsync代わりに使用してください:

rsync -a --delete foo/ bar/

ほんの少しだけ変更した場合、ディレクトリ全体を削除して再コピーするよりもはるかに速く実行されます。

  • -a忠実にファイルをコピーする「アーカイブモード」、であるfoo/のは、bar/
  • --deletefoo/からではない余分なファイルも削除しbar/、最終的にbar/同一になるようにします
  • それが何をしているのかを見たい場合は-vh、冗長で人間が読める形式を追加してください
  • 注:後のスラッシュfooは必須です。それ以外の場合rsyncは、それ自体を上書きfoo/するのbar/foo/ではなくコピーしますbar/
    • (rsyncの中のディレクトリの後にスラッシュが混乱している、あなたは、ここでスクープ興味を持っている場合、彼らはを参照するためにrsyncを伝える。内容ディレクトリではなく、ディレクトリの自体だから、から上書きする。コンテンツfoo/内容にbar/、我々 、両方のスラッシュを使用し、それは動作しませんので、上のスラッシュで予想通りそれは混乱しています。どちらもかかわらず、;それがソース上のスラッシュの有無を尊重するにもかかわらず、スラッシュを持っているかのようにこそこそ常にrsyncが先パスを解釈しますパスです。ディレクトリではなくの内容foo/にコピーする場合は、ソースパスにスラッシュが必要です。bar/foo/それ自体がbar/として着陸しますbar/foo。)

rsync 他に何ができるか(sshを介したコピーなど)に興味がある場合は、非常に強力で便利です。


1
より良いよりも、この答えのようにcp -T、それはまた、MacOSXの👍上で動作しますので、オプション
tongueroo

18

次のcpコマンドを使用します。

cp -Rf foo/* bar/

9
これは、barには存在するがfooには存在しないファイルは削除しません。
アラ

5
どういう意味かわからない。cpコマンドがソースからファイルを削除する必要があるのはなぜですか?
anubhava 2015

私の理解では、「既存のディレクトリを別のディレクトリで上書きする」と、最後に、上書きされたディレクトリは別のディレクトリのコピーになるはずです。つまり、@ jonathan-wheeler回答の場合と同様に、末尾のバーはfooのコピーである必要がありますが、ファイルbar / cがあり、foo / cがない場合、bar / cは削除されません。余談ですが、Saurabh Meshramの回答にも当てはまらないことに気づきました。
2015

多分私達は上書きが何を意味するかについて同意しません、私にとってそれは基本的に置換ですが、あなたはmegreを意味するかもしれませんか?彼女はfooとbarの両方にある2つのファイルしか言及していないので、OPが何を望んでいるかを正確に判断することは困難です。
Ara

この構文では、非表示のドットファイルも無視されます。多数がグロブを爆破する可能性もあります。
xpusostomos

13

次のコマンドは、ドットファイル(隠しファイル)がコピーに含まれるようにします。

$ cp -Rf foo/. bar

1
これは本当ですか?異常に見えます。
Mateng

2
@Mateng私はそれをテストしました-はい、それは本当です。
Matmarbon 2017

1
.ディレクトリ内のすべてのファイルを意味します。したがって、当然、隠しファイルも含まれます。
Jaspreet Singh 2018

それは実際にはかなりきれいです。Linuxで「cp -RTf foo bar」を実行することもできます。
xpusostomos

5

@Jonathan Wheelerに非常に似ています。

覚えたくないが書き直したくない場合bar

rm -r bar/
cp -r foo/ !$

!$ 前のコマンドの最後の引数を表示します。


4
!$に関するヒントは素晴らしいです!
Lucas Morgan、

0

これで問題が解決するはずです。

\cp -rf foo/* bar/

-1

定義した操作は「マージ」であり、では実行できませんcp。ただし、マージして[OK]フォルダを失うことを探していない場合bar、あなたは簡単にすることができrm -rf bar、その後、フォルダを削除すると、mv foo barその名前を変更します。どちらの操作もファイルの内容ではなくファイルポインタによって行われるため、これには時間がかかりません。


-2

次の2つのステップで構成されるコマンドを使用してみてください。

rm -rf bar && cp -r foo bar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.