Search code examples
msbuildmsbuild-4.0

MSBuild using %(RecursiveDir) as part of file name


As part of our build script we copy user messages files from a subdirectory and want to append the name of the subdirectory to the message files. i.e. msg\0\message.std > msg\message0.std

I have tried using

<Copy SourceFiles="@(MessageFiles)" 
DestinationFiles="@(MessageFiles->'$(BuildRoot)\%(Filename)%(RecursiveDir)%(Extension)'"/>

However this tries to copy the file to ..\message0.std.

Is there anyway to either suppress the trailing '\' from %(RecursiveDir) or make up the destination name another way?


Solution

  • You can do something like the following:

    <Target Name="DoIt">
        <ItemGroup>
            <MessageFiles2 Include="@(MessageFiles)">
                <SubDir>$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName(%(MessageFiles.RecursiveDir)))))</SubDir>
            </MessageFiles2>
        </ItemGroup>
        
        <Message Text="@(MessageFiles2->'$(BuildRoot)\%(Filename)%(SubDir)%(Extension)')"/>
        
    </Target>
    

    or if you wish to blow up the mind of the person who'll try to maintain your work:

    <Target Name="DoIt">
        <Message Text="@(MessageFiles->'$(BuildRoot)\%(Filename)$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName($([System.String]::Copy('%(MessageFiles.RecursiveDir)'))))))%(Extension)')"/>
    </Target>
    

    This is not a complete solution, but you can start from here. Also note that both above examples will break if RecursiveDir is empty i.e. your message file lies directly at the root folder.
    You can find more information in MSBuild Property Functions blog post.

    As an another way to handle your problem you can always create Custom Task.