msbuild를 사용하여 모든 파일 및 폴더 복사


94

누군가 내가 작성하려는 msbuild 스크립트로 나를 도울 수 있는지 궁금합니다. 내가하고 싶은 것은 msbuild를 사용하여 폴더의 모든 파일과 하위 폴더를 다른 폴더로 복사하는 것입니다.

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

내가 할 수 있어야 할 일은 도구 폴더의 모든 파일과 하위 폴더를 응용 프로그램의 디버그 폴더로 복사하는 것입니다. 이것이 제가 지금까지 가지고있는 코드입니다.

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

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

빌드 스크립트는 실행되지만 파일 또는 폴더를 복사하지 않습니다.

감사

답변:


136

나도 이것에 대한 도움을 찾고 있었다. 시간이 좀 걸렸지 만 여기 제가 한 일이 정말 잘 작동했습니다.

<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
잘 작동합니다-감사합니다! 왜 다른 더 복잡한 답변에 더 많은 찬성표가 있는지 궁금합니다!
이반

18
트릭은 %(RecursiveDir)대상 폴더에 추가 하면 디렉토리 구조가 다시 생성되는 것 같습니다 . 그렇지 않으면 출력이 평평합니다. 이것이 최고의 답변입니다.
JB. 모니카 랑.

1
.fsproj 파일 의 맨 아래 에 있어야합니다. 그렇지 않으면 그렇지 않습니다.
Henrik

나를 위해 일한 중요한 순간은 AfterBuild 대상 아래에서 변수 선언 ( <ANTLR Include = ".. \ Data \ antlrcs ***. *"/> )을 이동하는 것입니다. 제 경우에는 외부 범위에서 선언되었고 작동하지 않았습니다.
Shpand

72

항목 그룹을 만들고 복사 작업을 호출하는 방법에 문제가있을 수 있습니다. 이것이 의미가 있는지 확인하십시오.

<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 Task가 이와 같은 상황에 편리하다는 것을 알았습니다. 나는 내 프로젝트에서 같은 도전을 만났고 이것은 나를 위해 일했고 훨씬 간단했습니다. 누군가가 좋은 습관이 아니라면 알려주세요.

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

9
나는 감히 그 반대의 질문을한다. 로그 채우기 msbuild 복사 작업을 사용할 이유가 있습니까?
bernd_k 2012

4
잠재적으로. 빌드 팜 (Jenkins, TeamCity 등)이있는 경우 에이전트 서비스는 경로에 xcopy가없는 다른 계정으로 실행될 수 있습니다. 경로에서 % windir % \ system32와 같은 것을 시도 할 수 있지만이 경우에도 작동하지 않습니다.
Andrew dh 2013

그것이 나를 위해 일한 솔루션입니다. 또한 WorkingDirectory를 설정할 필요가 없습니다.
Aebsubis

참고로, 파일 / 폴더 재정의 프롬프트를 표시하지 않으려면 / Y를 추가해야합니다. 또한 $ (DeploymentDirectory)가 폴더 인 경우 경로 뒤에 "\"를 남겨두면 "destination is folder or file?"프롬프트가 제거됩니다.
Hoàng Long

6
이 문제가 자주 발생하지 않는다는 것을 알고 있지만 Copy명령 대신 작업 을 사용하는 주된 이유 는 호환성입니다. 전에 Mono를 사용하여 Linux에서 빌드했으며 분명히 xcopy거기에서 작동하지 않습니다.
GregRos

13
<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는 굉장 할 수 있지만 때로는 문서화가 잘 안된 쓰레기입니다.
The Muffin Man

CreateItem작업은 더 이상 사용되지 않습니다. 정규식에는 대안이 있습니다. msdn.microsoft.com/en-us/library/s2y3e43x.aspx
Ray Cheng

4

대신 구체적인 대상 디렉토리를 지정하려고 했습니까?

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

저는 고급 MSBuild 구문에 능숙하지 않지만

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

나에게 이상해 보인다. 스크립트가 좋아 보이므로 문제는 다음 값에있을 수 있습니다.$(ApplicationDirectory)$(OutputPath)

편집하다:

다음은 유용 할 수있는 블로그 게시물입니다.

방법 : 작업을 사용하여 재귀 적으로 파일 복사


1
링크의 +1은 zXen에서 수락 한 답변보다 더 간결합니다.
bernd_k 2012

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를 사용하여 한 디렉터리에서 다른 디렉터리로 파일을 재귀 적으로 복사하는 가장 좋은 방법은 SourceFiles 및 DestinationFiles를 매개 변수로 사용하는 복사 작업을 사용하는 것입니다. 예를 들어-빌드 디렉토리에서 백업 디렉토리로 모든 파일을 복사하려면

<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 ++ 도구 모음으로 작업하는 경우 다른 방법은 표준 CopyFileToFolders 목록에 파일을 추가하는 것입니다.

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

단순한 것 외에도 CopyFilesToFolders 작업이 적절한 입력, 출력 및 TLog 파일을 생성 하므로 입력 파일 중 하나가 변경되거나 출력 파일 중 하나가 누락 된 경우에만 복사 작업이 실행되도록 하기 때문에 이것은 좋은 방법 입니다. TLog를 사용하면 Visual Studio는 프로젝트를 "최신"으로 올바르게 인식합니다 (별도의 U2DCheck 메커니즘 사용).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.