Попытка исключить определенные расширения, делающие рекурсивное копирование (MSBuild)

Я пытаюсь использовать MSBuild для чтения списка файлов из текстового файла, а затем выполнить рекурсивное копирование, копируя содержимое этих файлов каталогов в некоторую промежуточную область, исключая при этом определенные расширения (например, файлы.tmp).

Мне удалось довольно легко выполнить большинство из перечисленного выше, используя CreateItem и задачу копирования MSBuild, что бы я ни делал, задача CreateItem просто игнорирует мой параметр Exclude:

<PropertyGroup>
  <RootFolder>c:\temp</RootFolder>
  <ExcludeFilter>*.tmp</ExcludeFilter>
  <StagingDirectory>staging</StagingDirectory>
</PropertyGroup>
<ItemGroup>
  <InputFile Include="MyFile.txt" />
</ItemGroup>

<Target Name="Build">
  <ReadLinesFromFile File="@(InputFile)">
    <Output ItemName="AllFolders" TaskParameter="Lines" />
  </ReadLinesFromFile>

  <CreateItem Include="$(RootFolder)\%(AllFolders.RelativeDir)**"
              Exclude="$(ExcludeFilter)">
    <Output ItemName="AllFiles" TaskParameter="Include" />
  </CreateItem>

  <Copy SourceFiles="@(AllFiles)"
        DestinationFolder="$(StagingDirectory)\%(RecursiveDir)" 

Пример содержимого файла "MyFile.txt":

somedirectory\
someotherdirectory\

(То есть пути относительно $(RootFolder) - упомяните это, потому что я где-то читал, что это может быть актуально)

Я перепробовал множество различных комбинаций фильтров исключения, но, похоже, я никогда не смог заставить его корректно исключать мои файлы.tmp - есть ли способ сделать это с MSBuild, не прибегая к xcopy?

1 ответ

Решение

Вы должны указать Exclude в абсолютном пути и измените подстановочный знак исключения, чтобы включить подкаталог

Если вы используете абсолютный путь для Include, вы должны использовать абсолютный путь для Exclude, Если вы используете относительный путь для IncludeВы должны использовать относительный путь для обоих.

<PropertyGroup>
  <RootFolder>c:\temp</RootFolder>
  <ExcludeFilter>**\*.tmp</ExcludeFilter>
  <StagingDirectory>staging</StagingDirectory>
</PropertyGroup>
<ItemGroup>
  <InputFile Include="MyFile.txt" />
</ItemGroup>

<Target Name="Build">
  <ReadLinesFromFile File="@(InputFile)">
    <Output ItemName="AllFolders" TaskParameter="Lines" />
  </ReadLinesFromFile>

  <CreateItem Include="$(RootFolder)\%(AllFolders.RelativeDir)**"
              Exclude="$(RootFolder)\%(AllFolders.RelativeDir)$(ExcludeFilter)">
    <Output ItemName="AllFiles" TaskParameter="Include" />
  </CreateItem>

  <Copy SourceFiles="@(AllFiles)"
        DestinationFolder="$(StagingDirectory)\%(RecursiveDir)"/>
</Target>

Несколько исключений и абсолютный путь

Если вы хотите исключить несколько элементов, не существует чистого способа, когда вы используете абсолютный путь, но вы могли бы сделать с Remove,

Первый способ: использование Remove и item

<PropertyGroup>
  <RootFolder>c:\temp</RootFolder>
</PropertyGroup>

<ItemGroup>
  <InputFile Include="MyFile.txt" />
  <!-- Exclude are defined here -->
  <ExcludeFilters Include="$(RootFolder)\**\*.tmp"/>
  <ExcludeFilters Include="$(RootFolder)\**\*.bmp"/>
</ItemGroup>

<Target Name="Build">
  <ReadLinesFromFile File="@(InputFile)">
    <Output ItemName="AllFolders" TaskParameter="Lines" />
  </ReadLinesFromFile>

  <CreateItem Include="$(RootFolder)\%(AllFolders.RelativeDir)**">
    <Output ItemName="AllFiles" TaskParameter="Include" />
  </CreateItem>

  <!-- Removing the wrong extension in item -->
  <ItemGroup>
    <AllFiles Remove="@(ExcludeFilters)"/>
  </ItemGroup>

  <Copy SourceFiles="@(AllFiles)"
        DestinationFolder="$(StagingDirectory)\%(RecursiveDir)"/>
</Target>

Второй способ: использование Remove и условие

<Target Name="Build">
  <ReadLinesFromFile File="@(InputFile)">
    <Output ItemName="AllFolders" TaskParameter="Lines" />
  </ReadLinesFromFile>

  <CreateItem Include="$(RootFolder)\%(AllFolders.RelativeDir)**">
    <Output ItemName="AllFiles" TaskParameter="Include" />
  </CreateItem>

  <!-- Removing the wrong extension in item -->
  <ItemGroup>
    <AllFiles Remove="@(AllFiles)" Condition="'%(Extension)' == '.tmp'"/>
    <AllFiles Remove="@(AllFiles)" Condition="'%(Extension)' == '.bmp'"/>
  </ItemGroup>

  <Copy SourceFiles="@(AllFiles)"
        DestinationFolder="$(StagingDirectory)\%(RecursiveDir)"/>
</Target>
Другие вопросы по тегам