msbuildを使用してすべてのファイルとフォルダーをコピーする


93

誰かが私が書こうとしているmsbuildスクリプトで私を助けることができるかどうか疑問に思っています。msbuildを使用して、すべてのファイルとサブフォルダをフォルダから別のフォルダにコピーします。

{ProjectName}
      |----->Source
      |----->Tools
              |----->Viewer
                       |-----{about 5 sub dirs}

私ができる必要があるのは、すべてのファイルとサブフォルダーをtoolsフォルダーからアプリケーションのデバッグフォルダーにコピーすることです。これは私がこれまでに持っているコードです。

 <ItemGroup>
<Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
 </ItemGroup>

<Target Name="BeforeBuild">
        <Copy SourceFiles="@(Viewer)" DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" />
  </Target>

ビルドスクリプトは実行されますが、ファイルやフォルダはコピーされません。

ありがとう

回答:


133

私もこれについて助けを求めていました。しばらく時間がかかりましたが、ここで私が実際にうまくいったことを行います。

<Target Name="AfterBuild">
    <ItemGroup>
        <ANTLR Include="..\Data\antlrcs\**\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>

これにより、という名前のフォルダーの内容が再帰的にコピーされantlrcsました$(TargetDir)


4
はい、これが最良の答えです。msdnブログで推奨されているものと同じ:blogs.msdn.com/b/msbuild/archive/2005/11/07/490068.aspx
Karsten

2
正常に動作します-ありがとうございます!他のより複雑な回答の方が賛成票が多いのはなぜですか。
Ivan

17
トリックは%(RecursiveDir)、宛先フォルダに追加するとディレクトリ構造が再作成されることのようです。それ以外の場合、出力はフラットです。これがベストアンサーです。
JB。モニカと。

1
.fsprojファイルの下部に配置する必要があります。
Henrik

ここで私にとってうまくいった重要な瞬間は、AfterBuildターゲットの下で変数宣言(<ANTLR Include = ".. \ Data \ antlrcs ***。*" />)を移動することです。私の場合、それは外側のスコープで宣言され、機能しませんでした。
シュパンド

71

問題は、ItemGroupを作成し、Copyタスクを呼び出す方法にあると思います。これが理にかなっているかどうかを確認します。

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    <PropertyGroup>
        <YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
        <YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
    </PropertyGroup>

    <Target Name="BeforeBuild">
        <CreateItem Include="$(YourSourceDirectory)\**\*.*">
            <Output TaskParameter="Include" ItemName="YourFilesToCopy" />
        </CreateItem>

        <Copy SourceFiles="@(YourFilesToCopy)"
                DestinationFiles="@(YourFilesToCopy->'$(YourDestinationDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" />
    </Target>
</Project>

CreateItemタスクは廃止されました。正規表現には代替手段があります。msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

35

MSBuildは初めての方ですが、このような状況ではEXECタスクが便利です。私のプロジェクトでも同じ課題に遭遇しましたが、これはうまくいき、はるかに簡単になりました。誰かがそれが良い習慣でないかどうか私に知らせてください。

<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
    <Exec Command="xcopy.exe  $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>

9
私はあえて逆の質問をします。ログ作成のmsbuild copyタスクを使用する理由はありますか?
bernd_k

4
潜在的に。ビルドファーム(Jenkins、TeamCityなど)がある場合、エージェントサービスは、パスにxcopyがない別のアカウントで実行される可能性があります。パスで%windir%\ system32のようなものを試すことができますが、これでも機能しない場合があります。
Andrew dh 2013

それは私のために働いたソリューションです。また、WorkingDirectoryを設定する必要もありませんでした。
Aebsubis 2015年

ちなみに、ファイル/フォルダーの上書きプロンプトを抑制するために/ Yを追加する必要があります。また、$(DeploymentDirectory)がフォルダーの場合、パスの後に「\」を残すと、「宛先はフォルダーまたはファイルですか?」というプロンプトが削除されます。
ホアンロング

6
この問題が頻繁に発生しないことはわかっていCopyますが、コマンドの代わりにタスクを使用する主な理由は互換性です。以前にMonoを使用してLinuxでビルドしたことがあり、明らかにxcopyそこでは機能しません。
GregRos

12
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    <PropertyGroup>
        <YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
        <YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
    </PropertyGroup>

    <Target Name="BeforeBuild">
        <CreateItem Include="$(YourSourceDirectory)\**\*.*">
            <Output TaskParameter="Include" ItemName="YourFilesToCopy" />
        </CreateItem>

        <Copy SourceFiles="@(YourFilesToCopy)"
                DestinationFiles="$(YourFilesToCopy)\%(RecursiveDir)" />
    </Target>
</Project>

\**\*.*すべてのフォルダからファイルを取得するのに役立ちます。RecursiveDirは、すべてのファイルをそれぞれのフォルダーに配置するのに役立ちます...


2
宛先ファイルは1項目を参照し、ソースファイルは33項目を参照します。同じ数のアイテムが必要です。ええと。msbuildはすばらしいものですが、ドキュメントが不十分で、ジャンクの一部である場合があります。
マフィン男14

CreateItemタスクは廃止されました。正規表現には代替手段があります。msdn.microsoft.com/en-us/library/s2y3e43x.aspx
レイ・チェン

4

代わりに具体的な宛先ディレクトリを指定しようとしましたか

DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" ? 

私は高度なMSBuild構文にあまり熟達していませんが、

@(Viewer->'$(OutputPath)\\Tools') 

私には奇妙に見えます。問題はの値であるかもしれないので、スクリプトは、よさそうだ$(ApplicationDirectory)$(OutputPath)

編集:

役立つかもしれないブログ投稿は次のとおりです。

方法:タスクを使用してファイルを再帰的にコピーする


1
リンクの+1。これは、zXenから受け入れられた回答よりも簡潔です。
bernd_k

3

これはうまくいった例です:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <ItemGroup>
      <MySourceFiles Include="c:\MySourceTree\**\*.*"/>
   </ItemGroup>

   <Target Name="CopyFiles">
      <Copy
        SourceFiles="@(MySourceFiles)"
        DestinationFiles="@(MySourceFiles->'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
       />
    </Target>

</Project>

ソース:https : //msdn.microsoft.com/en-us/library/3e54c37h.aspx


2

これは私が自分のプロジェクトで使用したコピータスクであり、サブフォルダーを含むフォルダーをコピー先に正常にコピーするために完全に機能していました:

<ItemGroup >
<MyProjectSource Include="$(OutputRoot)/MySource/**/*.*" />
</ItemGroup>

<Target Name="AfterCopy" AfterTargets="WebPublish">
<Copy SourceFiles="@(MyProjectSource)" 
 OverwriteReadOnlyFiles="true" DestinationFolder="$(PublishFolder)api/% (RecursiveDir)"/>

私の場合、プロジェクトの発行フォルダーを別の宛先フォルダーにコピーしましたが、これはあなたのケースと同様です。



0

MSBuildを使用して1つのディレクトリから別のディレクトリにファイルを再帰的にコピーする最良の方法は、パラメーターとしてSourceFilesおよびDestinationFilesを指定したCopyタスクを使用することです。例-ビルドディレクトリからバックアップディレクトリにすべてのファイルをコピーするには

<PropertyGroup>
<BuildDirectory Condition="'$(BuildDirectory)' == ''">Build</BuildDirectory>
<BackupDirectory Condition="'$(BackupDiretory)' == ''">Backup</BackupDirectory>
</PropertyGroup>

<ItemGroup>
<AllFiles Include="$(MSBuildProjectDirectory)/$(BuildDirectory)/**/*.*" />
</ItemGroup>

<Target Name="Backup">
<Exec Command="if not exist $(BackupDirectory) md $(BackupDirectory)" />
<Copy SourceFiles="@(AllFiles)" DestinationFiles="@(AllFiles-> 
'$(MSBuildProjectDirectory)/$(BackupDirectory)/%(RecursiveDir)/%(Filename)% 
(Extension)')" />
</Target>

上記の[コピー]コマンドで、すべてのソースディレクトリがトラバースされ、ファイルが宛先ディレクトリにコピーされます。


0

一般的なC ++ツールチェーンを使用している場合、もう1つの方法は、ファイルを標準のCopyFileToFoldersリストに追加することです。

<ItemGroup>
  <CopyFileToFolders Include="materials\**\*">
    <DestinationFolders>$(MainOutputDirectory)\Resources\materials\%(RecursiveDir)</DestinationFolders>
  </CopyFileToFolders>
</ItemGroup>

CopyFilesToFoldersタスクは適切な入力、出力、さらにはTLogファイルを生成するため、単純であるだけでなく、これは良い方法です。したがって、入力ファイルの1つが変更された場合、または出力ファイルの1つが欠落している場合にのみコピー操作が実行されるようにします。TLogを使用すると、Visual Studioはプロジェクトを「最新」であるかどうかを正しく認識します(そのために別のU2DCheckメカニズムを使用します)。

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