cpを使用してfolder等な方法でフォルダを再帰的にコピーする方法は?


46

使用するとき

cp -R inputFolder outputFolder

結果はコンテキスト依存です:

  1. outputFolder存在しない場合は作成され、クローンフォルダのパスはになりますoutputFolder
  2. 場合outputFolderが存在する場合、作成されたクローンは次のようになりますoutputFolder/inputFolder

インストールスクリプトを作成したいので、これは恐ろしいことです。ユーザーが誤って2回実行した場合outputFolder、最初に作成され、2回目の実行ですべてのものがもう一度作成されoutputFolder/inputFolderます。

  • 常に最初の動作が必要です:オリジナルの隣に(兄弟として)クローンを作成します。
  • cpポータブルにしたい(たとえば、MINGWはrsync出荷されていない)
  • 私はチェックしましたcp -R --parentsが、これはディレクトリツリーのすべての方法でパスを再作成します(したがって、クローンは作成されませんoutputFoldersome/path/outputFolder
  • --remove-destinationまたは--update、2が何も変更しない場合でも、物事はコピーされますoutputFolder/inputFolder

outputFolder(フォルダが存在しない場合は...)の存在を最初に確認せずにこれを行う方法はありますrm -rf outputFolderか?

合意された移植可能なUNIXの方法は何ですか?



2
これらのオプションの一部はPOSIXではないため、試したものはあまり移植性がありません。移植性が少し足りなくても生きられるのなら、使ってみませんrsyncか?
ムル

1
を使用する必要がない場合cp、2つのtarコマンド間のパイプは、ツリーをコピーするための優れた信頼できる方法です。
R ..

@R ..例を提供できますか?@muruこれがrsync出荷されていないMINGWで動作するようにします。
jakub.g

GNU tarでtar -C input -cf - . | tar -C output -xf -動作します。-C作業ディレクトリを変更しますが、これは標準オプションではないため、サポートされていない場合は、最初に正しい作業ディレクトリで2つのtarを実行する必要があり( cd input && tar -cf - . ) | ( cd output && tar -xf - )ます。
R ..

回答:


54

代わりにこれを使用してください:

cp -R inputFolder/. outputFolder

これは、たとえば機能するのとまったく同じようにcp -R aaa/bbb ccc機能します。ccc存在しない場合はbbb、そのコンテンツとそのコンテンツのコピーとして作成されます。ただし、ccc既に存在する場合ccc/bbbbbb、そのコンテンツのコピーとして作成されます。

ほとんどの場合、bbbこの質問で指摘した望ましくない動作が発生します。ただし、この特定の状況bbbでははだけ.であるためaaa/bbb、実際aaa/.にはaaaです。したがって、次の2つのシナリオがあります。

  1. ccc 存在しない:

    コマンドのcp -R aaa/. ccc意味は、「作成cccの内容とコピーaaa/.にはccc/.、すなわちコピーaaaccc

  2. ccc ある:

    コマンドのcp -R aaa/. ccc意味は「の内容をコピーaaa/.にしccc/.、すなわちコピーaaaccc


3
ええ、それは私にとって新しいものですが、それはうまくいくようです!これはどこでも文書化されていますか?
イルマリカロネン

1
inputFolder/.代わりにテストしましたがinputFolder、実際にWindows / Git Bashで動作します。(ただし、末尾だけでは機能しません/。スラッシュの後のドットも必要です)。面白いので+1を付けましたが、おそらく公開コードで使用するのは少しトリッキーすぎるかもしれません:)
jakub.g

@IlmariJaronen明示的に文書化する必要はありません。説明をたどると、それが単に「ルールに従う」ことがわかります。
ロアイマ

18

フォルダーをコピーせず、内容のみをコピーします。

## Create the target directory. The -p suppresses error messages
## if the directory already exists
mkdir -p outputFolder

## Copy the contents recursively, this will not recreate the parent
cp -R inputfolder/* outputfolder/

これにより、スクリプトの初回実行時にターゲットディレクトリが作成されるようにし、2回目に実行するときの問題を回避できます。

Chris Downは、bashでは、名前がで始まるファイルをスキップすることを非常に正確に指摘しています.。これを回避するには、shopt -s dotglob上記のコマンドを実行する前に実行できます。

両方-pのためにmkdir-Rのためにcp、これは完全に移植する必要がありますので、POSIXで定義されています。


6
注:で始まるファイルはコピーされません.。bashでは、dotglobそのために使用できます。
クリスダウン

2
glob展開がコマンドラインの最大長を超える可能性があるため、inputfolderのディレクトリエントリの数が多い場合、この方法は失敗する可能性が高いことに注意してください。
ティム・カッツ

11

-Tオプションを試してくださいcp。これは、GNU coreutils cpバージョン8.22に存在します。それ以外では移植できない場合があります。


1
:うん、私が望んでいたまさにているようですcp -Tcp --no-target-directory)。 unix.stackexchange.com/questions/94831/… 残念ながら私のバージョンcpはずっと古いです。
jakub.g

1
+1今日これを使用しました。-u遅延させるために追加するのに最適なオプションです。
PSkocik

4

また、使用することができますrsync

rsync -uav inputFolder/ outputFolder/

(特に最初のスラッシュの後のスラッシュに注意してください)


0

私の意見では、よりシンプルでポータブルなものはありませんrm -rf outputFolder。だから、私はいつもそれに固執しています。私はあなたの質問が異なることを理解していますが、これはベストプラクティスだと思います。


ターゲットに保持する必要がある特定のアクセス許可または所有権がある場合、これは失敗します。または、シンボリックリンクの場合。
ロアイマ

1
質問は、cpディレクトリが存在しない場合と存在する場合の両方の結果が同じであることを望んでいます。それで、あなたは何について話しているのですか?
-dashohoxha

cpOPで与えられるコマンドは、権限(またはタイムスタンプ)を保持しません。
ロアイマ

0

コマンドの-tオプションはcp次のように使用できます。

cp -R inputFolder -t outputFolder

ターゲットフォルダーが存在しない場合、エラーがスローされます。

cp: failed to access ‘outputFolder’: No such file or directory

上記のコマンドはinputFolder、コンテンツと一緒にコピーされます(その中のコンテンツだけではありません)

その内容だけをコピーしたい場合inputFolderは少しトリッキーになります(アスタリスク*を使用しながらシェルグロビングを使用する場合は注意する必要があるため)

cp -R  -t outputFolder/ -- inputFolder/*

ターゲットフォルダーが存在しない場合、エラーがスローされます。

cp: failed to access ‘outputFolder’: No such file or directory

で動作します cp (GNU coreutils) 8.23

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