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?
1 Answer 1
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 <tab>')
The Parameter attribute enables usage of the function in a pipeline (together with the PSPath alias).
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
}
Set-Content can be used instead of Out-File to bypass PowerShell's formatting step.
Get-NonReparsePointDirectoryFiles | foreach FullName | Set-Content -PassThru thefiles.txt