msbuild create itemgroup from property group

1.4k Views Asked by At

I want to pass a semi-colon separated list of strings.
Each string represents a file name.

    <PropertyGroup>
          <FileNames>Newtonsoft.Json;Reactive</FileNames>
          <PathToOutput>C:/</PathToOutput>
    </PropertyGroup>

Now I want to create an item group which should give me all the files in particular folder excluding list of Filename, something like:

<ItemGroup>
    <ReleaseFiles Include="$(PathToOutput)\**\*.*" Exclude="%(identity)-> identity.contains(%FileNames)"/>
</ItemGroup>

How do I iterate through current folder's files and match each ones name if it contains any one filename in Filenames variable.

2

There are 2 best solutions below

0
stijn On BEST ANSWER

Pretty sure this is a duplicate but I cannot find it at the moment so here it goes:

  • turning a semicolon-seperated property into an item is just a matter of using Include=$(Property)
  • Exclude only works if you have a list of exact matches, but you need more arbitrary filtering here so you'll need Condition
  • join the two ItemGroups together like a cross-product, by making those FileNames metadata of the ReleaseFiles item. Then you can iterate over each item in ReleaseFiles and have access to the FileNames at the same time
  • Contains is a property function (well, or a System::String method) so won't work as such on metadata, hence we turn metadata into a string first

In code:

<PropertyGroup>
  <FileNames>Newtonsoft.Json;Reactive</FileNames>
  <PathToOutput>C:/</PathToOutput>
</PropertyGroup>

<Target Name="FilterBasedCommaSeperatedProperty">
  <ItemGroup>
    <!-- property -> item -->
    <Excl Include="$(FileNames)"/>
    <!-- list all and add metadata list -->
    <AllReleaseFiles Include="$(PathToOutput)\**\*.*">
      <Excl>%(Excl.Identity)</Excl>
    </AllReleaseFiles >
    <!-- filter to get list of files we don't want -->
    <FilesToExclude Include="@(AllReleaseFiles)"
                    Condition="$([System.String]::Copy('%(FileName)').Contains('%(Excl)'))"/>
    <!-- all but the ones to exclude --> 
    <ReleaseFiles Include="@(AllReleaseFiles)" Exclude="@(FilesToExclude)"/>
  </ItemGroup>
  <Message Text="%(ReleaseFiles.Identity)" />
</Target>
0
Aaron Carlson On

Use the standard way to exclude files files from an item group by using the Exclude attribute and referencing another item group. It'll be much easier to understand.

Example:

<PropertyGroup>
  <PathToOutput>C:/</PathToOutput>
</PropertyGroup>

<ItemGroup>
    <FilesToExclude Include="$(PathToOutput)\**\Newtonsoft.Json" />
    <FilesToExclude Include="$(PathToOutput)\**\Reactive" />
    <ReleaseFiles Include="$(PathToOutput)\**\*.*" Exclude="@(FilesToExclude)"/>
</ItemGroup>