2011-03-21 112 views
15

我在文件夾內有一組文件。它們都有一個與DR __。*模式匹配的名稱。我想將它們複製到另一個文件夾,但刪除DR__前綴。我怎樣才能做到這一點與MSBuild?我曾經這樣做使用NAnt:MSBUild:使用基於原始文件的名稱複製文件

<mkdir dir="${ClientPath + '\bin\' + ConfigurationName + '\Parameters'}"/> 
<foreach item="File" property="Filename" in="CVParameters"> 
    <if test="${string::contains(Filename, Client + '_')}"> 
     <property name="newFilename" value="${ string::substring(Filename, string::last-index-of(Filename, '__') + 2, string::get-length(Filename) - string::last-index-of(Filename, '__') - 2) }"/> 
     <copy file="${ Filename }" tofile="${ ClientPath + '\bin\' + ConfigurationName + '\Parameters\' + newFilename }" overwrite="true"/> 
    </if> 
</foreach> 
+0

可能重複的[無法獲取MSBuild社區任務RegexReplace工作](http://stackoverflow.com/questions/7177257/cant-get-msbuild-community-task-regexreplace-towork) – 2016-04-13 13:23:56

回答

14

我同意@Si的解決方案。但使用MSBuild 4.0,您可以使用內置功能來完成。 NAnt腳本比我的更清晰。但我會添加它作爲一個解決方案只是爲了說明的MSBuild 4.0技術:

<ItemGroup> 
     <CVParameters Include="$(YourBaseDir)\**\DR__*" /> 
    </ItemGroup> 

    <Target Name="CopyAndRename" 
      Condition="'@(CVParameters)'!=''" 
      Outputs="%(CVParameters.Identity)"> 
     <PropertyGroup> 
      <OriginalFileName>%(CVParameters.FileName)%(CVParameters.Extension)</OriginalFileName>   
      <Prefix>DR__</Prefix> 
      <PrefixLength>$(Prefix.Length)</PrefixLength> 
      <OriginalFileNameLength>$(OriginalFileName.Length)</OriginalFileNameLength> 
      <SubstringLength>$([MSBuild]::Subtract($(OriginalFileNameLength),$(PrefixLength)))</SubstringLength> 
      <ModifiedFileName>$(OriginalFileName.Substring($(PrefixLength),$(SubstringLength)))</ModifiedFileName> 
      <DestinationFullPath>$([System.IO.Path]::Combine($(DestinationDir),$(ModifiedFileName)))</DestinationFullPath> 
     </PropertyGroup>                                   

     <Copy SourceFiles="%(CVParameters.FullPath)" 
       DestinationFiles="@(DestinationFullPath)" 
       SkipUnchangedFiles="true" /> 
    </Target> 

編輯(由OP):爲了得到這個工作,我曾與@(DestinationFullPath)更換$(DestinationFullPath)Copy,以匹配源的數量和目標文件。另外,我必須將前綴更改爲DR__,因爲DR__.不起作用。

+0

這個答案更直接,讓我走上了正確的軌道,給了我一種MSBuild技術的感覺。謝謝! – 2011-03-22 14:27:31

+0

無法弄清楚如何從外部調用該目標。 – 2011-11-24 15:07:12

2

你可以使用MSBuild 4.0嗎?如果是這樣,請參閱此answer(和MSDN help)。否則,MSBuildCommunityTasks中的RegexReplace任務也應該工作,但必須支持一個外部工具(如果可能,請去MSBuild 4.0)。

另一個(未測試)選項是MSBuildExtensionPack中的TextString任務。

失敗者,推出自己的任務?

+0

有關MSBuild的MSDN文檔有點欠缺,所以塞爾吉奧的回答更有幫助。但是我還沒有看到關於房地產功能的東西,所以也要感謝你。 – 2011-03-22 14:29:48

+0

沒問題達里奧,我同意塞爾吉奧的回答很有用! +1對我來說:) :) – si618 2011-03-23 03:30:19

2

我最近不得不做一些類似於此的事情,最後得到了一個基於內聯自定義任務的黑客行之有效的解決方案。

<UsingTask TaskName="GetNewFileName" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
    <ParameterGroup> 
     <OriginalFile ParameterType="System.String" Required="true" /> 
     <PackageVersion ParameterType="System.String" Required="true" /> 
     <NewFile Output="true" /> 
    </ParameterGroup> 
    <Task> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 

     int versionIndex = OriginalFile.IndexOf(PackageVersion); 
     versionIndex = versionIndex < 0 ? OriginalFile.Length : versionIndex; 

     NewFile = OriginalFile.Substring(0,versionIndex) + "nupkg"; 

     ]]> 
     </Code> 
    </Task> 
    </UsingTask> 

    <UsingTask TaskName="Combine" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
    <ParameterGroup> 
     <Path ParameterType="System.String" Required="true" /> 
     <File ParameterType="System.String" Required="true" /> 
     <FullPath Output="true" /> 
    </ParameterGroup> 
    <Task> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 
     FullPath = System.IO.Path.Combine(Path, File); 
    ]]> 
     </Code> 
    </Task> 
    </UsingTask> 

<Target Name="AfterCompile" Condition="'$(IsDesktopBuild)'!='true'"> 

    <ItemGroup> 
     <Nuspecs Include="$(SolutionRoot)\$(WorkingBranch)\Nuspec\**\*.nuspec"/> 
    </ItemGroup> 

    <!-- Build nugets --> 
    <Message Text="DEBUG: Build nuget packages" /> 
    <Exec 
     WorkingDirectory="$(NuspecsPath)" 
      Condition="" 
      Command='$(NugetPath) pack "%(Nuspecs.FullPath)" -Version 1.0.0.$(PackageVersion)' /> 

    <ItemGroup> 
     <Nupkgs2 Include="$(NuspecsPath)\**\*.nupkg"/> 
    </ItemGroup> 

    <GetNewFileName OriginalFile="%(Nupkgs2.FileName)%(Nupkgs2.Extension)" PackageVersion="$(PackageVersion)"> 
     <Output ItemName="RenamedNuPkgs" TaskParameter="NewFile"/> 
    </GetNewFileName> 

    <Combine File="%(RenamedNuPkgs.Filename)%(RenamedNuPkgs.Extension)" Path="$(NugetRepository)"> 
     <Output ItemName="PackagesRepository" TaskParameter="FullPath"/> 
    </Combine> 

    <Message Text="Renamed nuget packages: @(RenamedNuPkgs)"/> 
    <Message Text="Repository Renamed nuget packages: @(PackagesRepository)"/> 

    <Copy SourceFiles="@(Nupkgs2)" DestinationFiles="@(PackagesRepository)"/> 
+0

+1:我不知道這個選擇。感謝分享! – 2012-04-24 16:16:27

10

最近我不得不解決類似的任務,我使用Item的元數據。 此解決方案的優點是:

  1. 小生成腳本大小。
  2. 使用標準System.String函數來獲取修改後的名稱。
  3. 自定義元數據與新項目的定義複製,即基於現有的項目(例如項目<TempItemsBak Include="@(TempItems-> ... CustomTransform ...)">將獲得原項目的元數據值,所以你可以使用它進行進一步處理)

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

<PropertyGroup> 
    <InputDir Condition="'$(InputDir)' == '' ">.</InputDir> 
    <OutputDir Condition="'$(OutputDir)' == '' ">Output</OutputDir> 
    </PropertyGroup> 

    <ItemGroup> 
    <CVParameters Include="$(InputDir)\**\DR__.*" /> 
    </ItemGroup> 

    <Target Name="CopyNoPrefix"> 
    <ItemGroup> 
     <!-- Items with new name. Use System.String's Remove method to get full file name without prefix --> 
     <!-- http://msdn.microsoft.com/en-us/library/vstudio/ee886422(v=vs.100).aspx --> 
     <TempItems Include="@(CVParameters->'%(Filename)%(Extension)'->Remove(0, 5))"> 
     <!-- Define metadata based on original item for next step --> 
     <OriginalPath>%(Identity)</OriginalPath> 
     <SavedRecursiveDir>%(RecursiveDir)</SavedRecursiveDir> 
     </TempItems> 
    </ItemGroup> 

    <!-- Use new items along with their metadata for copying --> 
    <Copy SourceFiles="@(TempItems->'%(OriginalPath)')" DestinationFiles="@(TempItems->'$(OutputDir)\%(SavedRecursiveDir)%(Identity)')" /> 
    </Target> 

</Project> 
相關問題