Reputation: 353
I have a powershell script, which is supposed to navigate folders and subfolders of a specified directory. Once at the lowest level (when there are no more sub-folders, but only files), it will process the files. For my example, let's assume I have the following folders and files:
c:\temp\filder1\file1.txt
c:\temp\filder2\file2.txt
c:\temp\filder3\file3.txt
The problem happens when I am trying to go from the lowest-level folder to processing files in that folder: $files = Get-ChildItem $folder. It seems that somehow the object folder is converted into just a string with the folder's name. I get the error, which is now using my user's default path with the folder name appended, which, of course, fails, because now such folder exists in my default path. The error is something like:
Get-ChildItem : Cannot find path 'C:\Users\my.name\Documents\Powershell\Powershell_Scripts\folder1' because it does not exist.
The path I would expect is 'c:\temp\folder1'
Here the simplified version of my script:
Param(
[Parameter(Position = 1)] [string] $source_share_full_path = "c:\temp\" # path to a top-level share
)
$folders = Get-ChildItem $source_share_full_path
#Loop through all the folders
ProcessAllSubfolders($folders)
function ProcessAllSubfolders($folderCollection) {
foreach ($folder in $folderCollection)
{
if ($folder.Subfolders.Count -gt 0)
{
ProcessAllSubfolders($folder.SubFolders)
}
else
{
Write-Output "`nReady to process files in a folder : $folder.FullName `n "
$files = Get-ChildItem $folder.FullName
ProcessFiles($files)
}
}
}
function ProcessFiles($files) {
foreach ($file in $files)
{
Write-Output "`nReady to process file: $file `n "
}
}
The credit for the method of navigating sub-folders belongs here
I appreciate any pointers!
Upvotes: 0
Views: 1231
Reputation: 29048
As I commented, but am fleshing out a bit here:
$folder.Subfolders
property, so the count of subfolders will never work as intended. ()
for the parameters, e.g. ProcessFiles($files)
should be ProcessFiles $files
$folders = Get-ChildItem $source_share_full_path
you call the result $folders
, but they aren't folders, they are files and folders mixed.Unless you need to recurse down through the folders yourself, or plan to come back to the other folders later, how about something like:
Param(
[Parameter(Position = 1)] [string] $root_path = "c:\temp\"
)
$folders = Get-ChildItem $root_path -Directory -Recurse |
Where {$_.GetDirectories().Count -eq 0}
foreach ($folder in $folders) {
$files = Get-ChildItem $folder.FullName -File
foreach ($file in $files) {
Write-Host "Ready to process file $($file.FullName)"
}
}
Upvotes: 2
Reputation: 174990
The SubFolders
property in the example you reference is specific to SharePoint folders - it doesn't exist on FileSystemInfo
objects, which is what Get-ChildItem returns from the file system provider.
You can use Get-ChildItem $Path -Directory
to retrieve the subdirectories of $Path
, and Get-ChildItem
.
You might also want to add a CmdletBinding
attribute to your functions and declare the parameters properly:
function ProcessAllSubfolders {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[System.IO.DirectoryInfo[]]$FolderCollection
)
foreach ($Folder in $FolderCollection)
{
$SubFolders = @(Get-ChildItem $Folder.FullName -Directory)
if ($SubFolders.Count -gt 0)
{
ProcessAllSubfolders -FolderCollection $SubFolders
}
else
{
Write-Verbose "Ready to process files in a folder : $($Folder.FullName)"
$Files = Get-ChildItem $folder.FullName
ProcessFiles $files
}
}
}
function ProcessFiles {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[System.IO.FileInfo[]]$Files
)
foreach ($File in $Files)
{
Write-Verbose "Ready to process file: $File"
# Do your processing on $File here
}
}
Now you can call ProcessAllSubfolders
with the -Verbose
switch if you the messages written to the console:
$InitialFolders = Get-ChildItem $SourcePath -Directory
#Loop through all the folders
ProcessAllSubfolders -FolderCollection $InitialFolders
Save the script, and voila:
PS C:\> ProcessFiles.ps1 -Verbose
VERBOSE: Ready to process files in a folder : C:\temp\text\x
VERBOSE: Ready to process file: n_238633.log
VERBOSE: Ready to process file: n_895226.log
Upvotes: 2