简体   繁体   中英

Check if a path is a folder or a file in PowerShell

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?

I found a workaround for this question: use Test-Path cmdlet with the parameter -FileType 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 .

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, eg

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}
        }
  }

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. eg

$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.

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
}

Yet another way is by using DirectoryInfo .

MWE from the file-name:

$(Get-Item c:\windows\system32) -is [System.IO.DirectoryInfo]

The comment (which I can't comment on) which says: "this is a totally disaster answer, "Container" and "Leaf" worries about regkeys not being dir or file,:. – TechDogLover OR kiaNasirzadeh Nov 12: 2021 at 16,49" is wrong. The official documentation from Microsoft makes it clear that "-PathType Container" is. "An element that contains other elements, such as a directory or registry key." Note the "OR".

So the answer from Alicia is NOT a DISASTER of an answer and is perfectly acceptable for the original poster's question. In fact the only disaster is the comment from TechDogLover OR kiaNasirzadeh.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM