I had occasion to write a script to find the Deepest path for a folder structure so that I could set some build properties for a .proj file in Visual Studio.
Knowing that I can use Get-ChildItem to recurse and give me all the directory objects I was half way home.
$folders = Get-ChildItem .\ -r -Directory
In order to get the path depth for each directory I had to split the path value and count the number of elements after the split. This gave me the total number of directories.
$filtered = $folders |Select-Object @{Name=‘FullName’;Expression={$_.fullname.replace($pwd,”)}}, @{Name=‘FolderDepth’;Expression={($_.fullname.Split(‘\’).Count) – ($Pwd.Path.split(‘\’).count)}} | Sort-Object -Descending FullName,folderDepth
I used the fact that I know where I presently am with the $pwd automatic variable. This allowed me to strip off the starting directory because I didnt’ care about where I was I wanted the depth relative to where I ran the command.
So the $_.fullname.replace($pwd,”) removed off the directory I started in.
Then after the split
($_.fullname.Split('\').Count) - ($Pwd.Path.split('\').count)
I counted up the total number for the split minus the total number of directories for the $PWD directory. Then I took that value and gave it a name ‘FolderDepth’. In the end I have a sortable object that looks like this:
FullName FolderDepth
-------- -----------
\utility\doc\site\images 4
\utility\doc\site 3
\utility\doc\scheduledtasklogs\images 4
\utility\doc\scheduledtasklogs 3
\utility\doc\logfiles\images 4
\utility\doc\logfiles 3
\utility\doc\doclib\images 4
\utility\doc\doclib 3
\utility\doc\dct_doc\images 4
\utility\doc\dct_doc 3
\utility\doc\communication\images 4
\utility\doc\communication 3
\utility\doc 2
\utility 1
\template\jqGrid\js 3
Now that I have the folder depth I can sort on the Base folder using this select statement:
$basefolders = $filtered | Where-Object{$_.folderdepth -eq 1}
Now I can loop through this basefolders object and retrieve the 1st
largest folder to find my deepest path:
foreach($basefolder in $basefolders)
{
$basefoldername =$baseFolder.fullname
$filteredbase = $filtered -match "\$basefoldername\\" | Sort-Object -Descending FolderDepth | Select-Object -first 1
if($filteredbase -eq $null)
{
$filteredbase = $filtered -match "\$basefoldername" | Sort-Object -Descending FolderDepth | Select-Object -first 1
}
$obj = New-Object psobject
Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Folder' -Value $basefolder.fullname.trim('\')
Add-member -InputObject $obj -MemberType NoteProperty -Name 'DeepestPath' -Value $filteredbase.folderDepth
$basefoldersobj += $obj
}
Which now gives me an object that looks like this:
Folder DeepestPath
------ -----------
utility 4
template 4
system 3
scheduled 4
schedule 4
reporting 2
report_library 2
Properties 1
obj 3
manage_template 1
manage_setup 1
manage_schedule 1
manage_report 1
manage_migration 1
manage_handheld 1
manage_dataconversion 1
manage_contact 1
manage_configuration 1
instance 1
images 6
doc 4
common 6
cfc 1
Build_ValidationReports 2
aspnet_client 3
So now I can create the add that I want for my content include in my csproj file:
$include = '*.*'
foreach($bfolderObj in $basefoldersobj)
{
$includecount = "\$include" * ($bfolderObj.Deepestpath)
Write-Output "<content Include=`"$($bfolderObj.folder)$includecount`" /> "
}
Which then gives me the output I’m looking for:
<content Include="utility\*.*\*.*\*.*\*.*" />
<content Include="template\*.*\*.*\*.*\*.*" />
<content Include="system\*.*\*.*\*.*" />
<content Include="scheduled\*.*\*.*\*.*\*.*" />
<content Include="schedule\*.*\*.*\*.*\*.*" />
<content Include="reporting\*.*\*.*" />
<content Include="report_library\*.*\*.*" />
<content Include="Properties\*.*" />
<content Include="obj\*.*\*.*\*.*" />
<content Include="manage_template\*.*" />
<content Include="manage_setup\*.*" />
<content Include="manage_schedule\*.*" />
<content Include="manage_report\*.*" />
<content Include="manage_migration\*.*" />
<content Include="manage_handheld\*.*" />
<content Include="manage_dataconversion\*.*" />
<content Include="manage_contact\*.*" />
<content Include="manage_configuration\*.*" />
<content Include="instance\*.*" />
<content Include="images\*.*\*.*\*.*\*.*\*.*\*.*" />
<content Include="doc\*.*\*.*\*.*\*.*" />
<content Include="common\*.*\*.*\*.*\*.*\*.*\*.*" />
<content Include="cfc\*.*" />
<content Include="Build_ValidationReports\*.*\*.*" />
<content Include=”aspnet_client\*.*\*.*\*.*” />
Full script is below:
$folders = Get-ChildItem .\ -r -Directory
$filtered = $folders |Select-Object @{Name='FullName';Expression={$_.fullname.replace($pwd,'')}}, @{Name='FolderDepth';Expression={($_.fullname.Split('\').Count) - ($Pwd.Path.split('\').count)}} | Sort-Object -Descending FullName,folderDepth
$basefolders = $filtered | Where-Object{$_.folderdepth -eq 1}
$basefoldersobj = @()
foreach($basefolder in $basefolders)
{
$basefoldername =$baseFolder.fullname
$filteredbase = $filtered -match "\$basefoldername\\" | Sort-Object -Descending FolderDepth | Select-Object -first 1
if($filteredbase -eq $null)
{
$filteredbase = $filtered -match "\$basefoldername" | Sort-Object -Descending FolderDepth | Select-Object -first 1
}
$obj = New-Object psobject
Add-Member -InputObject $obj -MemberType NoteProperty -Name 'Folder' -Value $basefolder.fullname.trim('\')
Add-member -InputObject $obj -MemberType NoteProperty -Name 'DeepestPath' -Value $filteredbase.folderDepth
$basefoldersobj += $obj
}
$include = '*.*'
foreach($bfolderObj in $basefoldersobj)
{
$includecount = ''
$includecount = "\$include" * ($bfolderObj.Deepestpath)
Write-Output "<content Include=`"$($bfolderObj.folder)$includecount`" /> "
}