HiveBrain v1.2.0
Get Started
← Back to all entries
patternshellMinor

Recursive Windows Directory listing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
listingrecursivewindowsdirectory

Problem

I wrote a PowerShell script for a superuser question:


list of all files and directories under a path recursively, without recursing into junction points or links

I have a strong feeling that my code is way too complicated for such a simple task.

function Recurse($path) {

  $fc = new-object -com scripting.filesystemobject
  $folder = $fc.getfolder($path)

  foreach ($i in $folder.files) { $i | select Path }

  foreach ($i in $folder.subfolders) {
    $i | select Path        
    if ( (get-item $i.path).Attributes.ToString().Contains("ReparsePoint") -eq $false) {        
        Recurse($i.path)
    }
  }
}

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$outputlist = Recurse($scriptPath) | Out-File -Filepath .\outputlist.txt


Short instructions on how to use the script:

  • Paste the code into a text file and save it as PowerShell (.ps1) script



  • Place the script inside a folder to list all files+folder recursively without junction folder loops



  • Execute the script. A new file called outputlist.txt at the same location will appear



Questions:

  • Can I simplify this PowerShell script anyhow?



  • Is there a better Out-command where no blank spaces are appended after every line?

Solution

Here's a shot at it: (Requires PowerShell v3 or higher)

The idea here is to get all non-reparsepoint directories first.
For each directory, recurse into the subdirectory and then output the files at the current level.

In it's simplest form, it looks like this:

function Get-ChildItemNoReparsePoint($Path)
{
    Get-ChildItem -Path $Path -Attributes !ReparsePoint -Directory | foreach { 
        Get-ChildItemNoReparsePoint $_.Fullname
    }
    Get-ChildItem -File $Path  
}


A more full example is shown below:

We hook into the powershell help system by adding specially formatted comment.

By adding the [CmdletBinding()] attribute, we get access to the powershell common parameters (Get-Help about_Common_Parameters).

By adding the OutputType attribute, you get tab completion after the command in the pipeline. (try 'Get-ChildItemNoReparsePoint| Foreach ')

The Parameter attribute enables usage of the function in a pipeline (together with the PSPath alias).

function Get-ChildItemNoReparsePoint
{

[CmdletBinding()]
[OutputType([System.IO.FileInfo])]
param(
    [Parameter(ValueFromPipelineByPropertyName)]
    [Alias('PSPath')]
    # Specifies a path to one or more locations.
    [string[]]$Path=$pwd
)
process
{
    Get-ChildItem -Path $Path -Attributes !ReparsePoint -Directory | Get-ChildItemNoReparsePoint       
    Get-ChildItem -File $Path
}


Set-Content can be used instead of Out-File to bypass PowerShell's formatting step.

Get-NonReparsePointDirectoryFiles | foreach FullName | Set-Content -PassThru thefiles.txt

Code Snippets

function Get-ChildItemNoReparsePoint($Path)
{
    Get-ChildItem -Path $Path -Attributes !ReparsePoint -Directory | foreach { 
        Get-ChildItemNoReparsePoint $_.Fullname
    }
    Get-ChildItem -File $Path  
}
function Get-ChildItemNoReparsePoint
{
<#
.SYNOPSIS
    Gets all files of a directory recursivly, excluding reparse points
.OUTPUTS
    System.IO.FileInfo
.EXAMPLE
dir | Get-ChildItemNoReparsePoint 
.EXAMPLE
Get-ChildItemNoReparsePoint ~/Documents | Foreach FullName | Set-Content thefiles.txt
.EXAMPLE
Get-ChildItemNoReparsePoint ~/Documents -OutVariable files | Foreach FullName | Set-Content thefiles.txt
$files | Group-Object Extension
#>
[CmdletBinding()]
[OutputType([System.IO.FileInfo])]
param(
    [Parameter(ValueFromPipelineByPropertyName)]
    [Alias('PSPath')]
    # Specifies a path to one or more locations.
    [string[]]$Path=$pwd
)
process
{
    Get-ChildItem -Path $Path -Attributes !ReparsePoint -Directory | Get-ChildItemNoReparsePoint       
    Get-ChildItem -File $Path
}
Get-NonReparsePointDirectoryFiles | foreach FullName | Set-Content -PassThru thefiles.txt

Context

StackExchange Code Review Q#29930, answer score: 3

Revisions (0)

No revisions yet.