给出一个目录列表:
<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>
但我想知道是否有更简单的方法。
答案 0 :(得分:2)
摘自“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)后,您可以使用Remove属性对其进行过滤,以删除Subversion文件夹。
答案 1 :(得分:1)
<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)\**\*.*"
,则会以递归方式包含所有子文件夹。
答案 2 :(得分:1)
使用完全独立的示例扩展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 answer获得了UsingTask示例。