I have a set of files inside a folder. They all have a name which matches the pattern DR__.*. I want to copy them to another folder, but removing the DR__ prefix. How can I do this with MSBuild? I used to do it like this using NAnt:
<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>
I agree with @Si's solution. But with MSBuild 4.0 you can do it with built in functionality. NAnt script is much clearer than mine. But I will add it as a solution just to show MSBuild 4.0 techniques:
<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>
Edit (by OP): To get this working, I had to replace $(DestinationFullPath)
in Copy
with @(DestinationFullPath)
, to match the number of Source and Destination Files. Also, I had to change the prefix to DR__
, since DR__.
wouldn't work.
Recently I had to solve similar task and I did it using Item's metadata. Advantages of this solution are:
<TempItemsBak Include="@(TempItems-> ... CustomTransform ... )">
will get original item's metadata values so you can use it for further processing)<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With