Reputation: 510
I'm trying to write a PowerShell script which goes through a list of values which are folder or file paths, and delete the files first, then remove the empty folders.
My script so far:
[xml]$XmlDocument = Get-Content -Path h:\List_Files.resp.xml
$Files = XmlDocument.OUTPUT.databrowse_BrowseResponse.browseResult.dataResultSet.Path
Now I'm trying to test each line in the variable to see if it's a file and delete it first, and then go through and remove subfolders and folders. This is just so that it's a clean process.
I can't quite get this next bit to work, but I think I need something like:
foreach ($file in $Files)
{
if (! $_.PSIsContainer)
{
Remove-Item $_.FullName}
}
}
The next section can clean up the subfolders and folders.
Any suggestions?
Upvotes: 49
Views: 69372
Reputation: 1
Yet another way is by using Get-ItemProperty
:
$PathObject = (Get-ItemProperty 'C:\somefolder')
if ($PathObject.Attributes -like '*Directory*') {
write-host 'It''s a directory'
} else {
write-host 'It''s a file'
}
Upvotes: 0
Reputation: 884
I found a workaround for this question: use Test-Path
cmdlet with the parameter -PathType
equal to Leaf
for checking if it is a file or Container
for checking if it is a folder:
# Check if file (works with files with and without extension)
Test-Path -Path 'C:\Demo\FileWithExtension.txt' -PathType Leaf
Test-Path -Path 'C:\Demo\FileWithoutExtension' -PathType Leaf
# Check if folder
Test-Path -Path 'C:\Demo' -PathType Container
I originally found the solution here. And the official reference is here.
Upvotes: 58
Reputation: 9045
Yet another way is by using DirectoryInfo
.
MWE from the file-name:
$(Get-Item c:\windows\system32) -is [System.IO.DirectoryInfo]
Upvotes: 3
Reputation: 1487
We can use get-item
command and supply the path. Then you can check PSIsContainer
(boolean) property that would determine whether the supplied path targets a folder or a file. e.g.
$target = get-item "C:\somefolder" # or "C:\somefolder\somefile.txt"
if($target.PSIsContainer) {
# it's a folder
}
else { #its a file }
Hope this helps any future visitors.
Upvotes: 19
Reputation: 11222
Consider the following code:
$Files = Get-ChildItem -Path $env:Temp
foreach ($file in $Files)
{
$_.FullName
}
$Files | ForEach {
$_.FullName
}
The first foreach is a PowerShell language command for looping, and the second ForEach is an alias for the ForEach-Object
cmdlet which is something completely different.
In the ForEach-Object
, the $_
points to the current object in the loop, as piped in from the $Files
collection, but in the first foreach, $_
has no meaning.
In the foreach loop use the loop variable $file
:
foreach ($file in $Files)
{
$file.FullName
}
Upvotes: 4
Reputation: 30248
I think that your $Files
object is an array of strings:
PS D:\PShell> $Files | ForEach-Object {"{0} {1}" -f $_.Gettype(), $_}
System.String D:\PShell\SO
System.String D:\PShell\SU
System.String D:\PShell\test with spaces
System.String D:\PShell\tests
System.String D:\PShell\addF7.ps1
System.String D:\PShell\cliparser.ps1
Unfortunately, the PSIsContainer
property cannot be found on a string object but on a filesystem object, e.g.
PS D:\PShell> Get-ChildItem | ForEach-Object {"{0} {1}" -f $_.Gettype(), $_}
System.IO.DirectoryInfo SO
System.IO.DirectoryInfo SU
System.IO.DirectoryInfo test with spaces
System.IO.DirectoryInfo tests
System.IO.FileInfo addF7.ps1
System.IO.FileInfo cliparser.ps1
To get a filesystem object from a string:
PS D:\PShell> $Files | ForEach-Object {"{0} {1}" -f (Get-Item $_).Gettype(), $_}
System.IO.DirectoryInfo D:\PShell\SO
System.IO.DirectoryInfo D:\PShell\SU
System.IO.DirectoryInfo D:\PShell\test with spaces
System.IO.DirectoryInfo D:\PShell\tests
System.IO.FileInfo D:\PShell\addF7.ps1
System.IO.FileInfo D:\PShell\cliparser.ps1
Try next code snippet:
$Files | ForEach-Object
{
$file = Get-Item $_ ### string to a filesystem object
if ( -not $file.PSIsContainer)
{
Remove-Item $file}
}
}
Upvotes: 6