获取msbuild中的子目录列表

发布于 2024-12-02 08:36:15 字数 1508 浏览 1 评论 0原文

给定目录列表:

<ItemGroup>
  <Dirs Include="Foo\Dir1" />
  <Dirs Include="Foo\Dir2" />
</ItemGroup>

如何获取所有子目录的列表。

使用 "$(Identity)\**" 转换此列表不会匹配任何内容,使用 "$(Identity)\**\*" 转换,然后使用 RelativeDir 仅生成包含文件的目录。

目前我必须求助于 C#:

<UsingTask TaskName="GetSubdirectories" TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <Directories ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
        <SubDirectories ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
        <Code Type="Fragment" Language="cs"><![CDATA[
            var result = new List<ITaskItem>();
            foreach (var dirItem in Directories) {
                foreach (var dir in Directory.GetDirectories(dirItem.ItemSpec, "*", SearchOption.AllDirectories)) {
                    if (dir.Contains(@"\.svn\") || dir.EndsWith(@"\.svn")) continue;
                    result.Add(new TaskItem(dir));
                }
            }
            SubDirectories = result.ToArray();
        ]]></Code>
    </Task>
</UsingTask>

<GetSubdirectories Directories="@(Dirs)">
    <Output TaskParameter="SubDirectories" ItemName="SubDirs" />
</GetSubdirectories>

但我想知道是否有更简单的方法。

Given a list of directories:

<ItemGroup>
  <Dirs Include="Foo\Dir1" />
  <Dirs Include="Foo\Dir2" />
</ItemGroup>

How can I get a list of all subdirectories.

Transforming this list with "$(Identity)\**" does not match anything and transforming with "$(Identity)\**\*" and then with RelativeDir yields only directories that contain files.

Currently I have to resort to C#:

<UsingTask TaskName="GetSubdirectories" TaskFactory="CodeTaskFactory"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <Directories ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
        <SubDirectories ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
        <Code Type="Fragment" Language="cs"><![CDATA[
            var result = new List<ITaskItem>();
            foreach (var dirItem in Directories) {
                foreach (var dir in Directory.GetDirectories(dirItem.ItemSpec, "*", SearchOption.AllDirectories)) {
                    if (dir.Contains(@"\.svn\") || dir.EndsWith(@"\.svn")) continue;
                    result.Add(new TaskItem(dir));
                }
            }
            SubDirectories = result.ToArray();
        ]]></Code>
    </Task>
</UsingTask>

<GetSubdirectories Directories="@(Dirs)">
    <Output TaskParameter="SubDirectories" ItemName="SubDirs" />
</GetSubdirectories>

But I would like to know if there is an easier way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

兮颜 2024-12-09 08:36:15

摘自《MSBuild Trickery》一书:

<Import Project="EnableAllPropertyFunctions.tasks" />

<Target Name="GetSubdirectories">
   <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::
         EnumerateDirectories(
            `.\Foo`,
            `*`,
            System.IO.SearchOption.AllDirectories))"
            />
   </ItemGroup>

   <Message Text="%(Dirs.Identity)" />
</Target>

您需要首先通过确保环境变量 MSBuildEnableAllPropertyFunctions 设置为值 1 来启用扩展属性函数集(这就是导入的 .tasks 文件通过内联任务完成的任务) 。

设置 @(Dirs) 后,您可以使用“删除”属性对其进行过滤以删除 Subversion 文件夹。

Excerpted from the book "MSBuild Trickery":

<Import Project="EnableAllPropertyFunctions.tasks" />

<Target Name="GetSubdirectories">
   <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::
         EnumerateDirectories(
            `.\Foo`,
            `*`,
            System.IO.SearchOption.AllDirectories))"
            />
   </ItemGroup>

   <Message Text="%(Dirs.Identity)" />
</Target>

You'll need to first enable the extended property function set by ensuring that the environment variable MSBuildEnableAllPropertyFunctions is set to the value 1 (that is what the imported .tasks file accomplishes, with an inline task).

Once @(Dirs) is set up, you can filter it with the Remove attribute to get rid of the Subversion folders.

深爱不及久伴 2024-12-09 08:36:15
<CreateItem Include="$(OutputFolder)\*\*.*">
  <Output TaskParameter="Include" ItemName="FilesInSubFolders" />
</CreateItem>

<RemoveDuplicates Inputs="@(FilesInSubFolders->'%(RelativeDir)')">
  <Output TaskParameter="Filtered" ItemName="SubDirs"/>
</RemoveDuplicates>

<Message Text="@(SubDirs)"/>

这会将所有直接子文件夹路径放入@(SubDirs)。如果将 Include="$(OutputFolder)\*\*.*" 更改为 Include="$(OutputFolder)\**\*.*",则将递归地包含所有子文件夹。

<CreateItem Include="$(OutputFolder)\*\*.*">
  <Output TaskParameter="Include" ItemName="FilesInSubFolders" />
</CreateItem>

<RemoveDuplicates Inputs="@(FilesInSubFolders->'%(RelativeDir)')">
  <Output TaskParameter="Filtered" ItemName="SubDirs"/>
</RemoveDuplicates>

<Message Text="@(SubDirs)"/>

This will put all the immediate subfolder paths into @(SubDirs). If you change Include="$(OutputFolder)\*\*.*" to Include="$(OutputFolder)\**\*.*", it'll include all subfolders recursively.

吻安 2024-12-09 08:36:15

为了用一个完全独立的示例来扩展 Brian 的答案:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GetSubdirectories">
  <UsingTask TaskName="SetEnvironmentVariable"
             TaskFactory="CodeTaskFactory"
             AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
    <ParameterGroup>
      <Name ParameterType="System.String" Required="true" />
      <Value ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs"><![CDATA[
        Environment.SetEnvironmentVariable(Name, Value);
      ]]></Code>
    </Task>
  </UsingTask>

  <Target Name="GetSubdirectories">
    <SetEnvironmentVariable Name="MSBuildEnableAllPropertyFunctions" Value="1" />
    <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::EnumerateFiles('.\Stuff', '*', System.IO.SearchOption.AllDirectories))"/>
    </ItemGroup>
    <Message Text="%(Dirs.Identity)" />
  </Target>
</Project>

我从 this 获取了UsingTask 示例回答

To expand on Brian's answer with a fully self-contained example:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GetSubdirectories">
  <UsingTask TaskName="SetEnvironmentVariable"
             TaskFactory="CodeTaskFactory"
             AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
    <ParameterGroup>
      <Name ParameterType="System.String" Required="true" />
      <Value ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs"><![CDATA[
        Environment.SetEnvironmentVariable(Name, Value);
      ]]></Code>
    </Task>
  </UsingTask>

  <Target Name="GetSubdirectories">
    <SetEnvironmentVariable Name="MSBuildEnableAllPropertyFunctions" Value="1" />
    <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::EnumerateFiles('.\Stuff', '*', System.IO.SearchOption.AllDirectories))"/>
    </ItemGroup>
    <Message Text="%(Dirs.Identity)" />
  </Target>
</Project>

I got the UsingTask example from this answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文