web-dev-qa-db-ja.com

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

私が使うとき

cp -R inputFolder outputFolder

結果はcontext-dependentです。

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

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

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

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

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

46
jakub.g

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

cp -R inputFolder/. outputFolder

これは、たとえばcp -R aaa/bbb cccと同じように機能します。cccが存在しない場合は、bbbとその内容のコピーとして作成されます。ただし、cccがすでに存在する場合は、bbbとその内容のコピーとしてccc/bbbが作成されます。

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にコピーします。

54
roaima

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

## 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 for mkdir-R for cp の両方がPOSIXで定義されているため、完全に移植可能である必要があります。

18
terdon

cp-Tオプションを試してください。これはGNU coreutils cpバージョン8.22に存在します;それ以外では移植できないかもしれません。

11
Tom Hunt

rsyncを使用することもできます:

rsync -uav inputFolder/ outputFolder/

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

4
Ned64

私の意見では、rm -rf outputFolderよりも単純で移植性の高いものはありません。だから、私はいつもそれにこだわる。あなたの質問は違うと思いますが、これがベストプラクティスだと思います。

0
dashohoxha

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

_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で動作します

0
Edward Torvalds