98

In Powershell, how do I test if a directory is empty?

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465

16 Answers16

91

If you are not interested in hidden or system files you can also use Test-Path

To see if it exists a file in directory .\temp you can use :

Test-Path -Path .\temp\*

or shortly :

Test-Path .\temp\*
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
72

Try this...

$directoryInfo = Get-ChildItem C:\temp | Measure-Object
$directoryInfo.count #Returns the count of all of the objects in the directory

If $directoryInfo.count -eq 0, then your directory is empty.

Doktor J
  • 1,058
  • 1
  • 14
  • 33
Boeckm
  • 3,264
  • 4
  • 36
  • 41
  • 9
    `gci` won't display hidden files by default, so you'll need the `-force` parameter to ensure the directory is truly empty. – SpellingD Jan 04 '13 at 16:36
  • 5
    Do we have to find each file? This can be time consuming. – MuiBienCarlota Dec 22 '14 at 12:02
  • @SpellingD that will fail because a folder is really empty, but using `-force` will turn up the `desktop.ini` hidden system file – mikew Oct 25 '17 at 17:34
  • 1
    "directoryInfo.count" does NOT return the count of all files in the directory, but rather it returns the count of all files AND sub-directories inside. so if you have 0 files but 1 sub-folder it returns 1. – Benjamin Apr 25 '19 at 12:36
  • @Benjamin edited for clarity. If you do want to only check if there are no _files_ in a directory, add the `-file` parameter to Get-ChildItem, e.g. `$directoryInfo = Get-ChildItem C:\temp -file | Measure-Object` – Doktor J Nov 22 '19 at 16:04
27

To prevent enumerating each file under c:\Temp (which can be time consuming), we can do somethings like this:

if((Get-ChildItem c:\temp\ -force | Select-Object -First 1 | Measure-Object).Count -eq 0)
{
   # folder is empty
}
MuiBienCarlota
  • 2,355
  • 1
  • 28
  • 32
  • This is by far the fastest solution as it doesn't enumerate through all files and just stops at the first one found. For checking if file(s) are present in a folder use `(Get-ChildItem -LiteralPath 'S:\Test\' -File -Force | Select-Object -First 1 | Measure-Object).Count -ne 0` instead of `Test-Path 'S:\Test\*' -PathType Leaf`. – DarkLite1 Feb 04 '16 at 13:29
  • 1
    Measure-Object isn't really adding anything here unless you're on PowerShell v1. – Bacon Bits Aug 07 '19 at 12:00
  • 2021 and this is still the fastest solution, by a long way. – Jose Vega Dec 19 '21 at 16:58
6
filter Test-DirectoryEmpty {
    [bool](Get-ChildItem $_\* -Force)
}
Joey
  • 344,408
  • 85
  • 689
  • 683
4

One line:

if( (Get-ChildItem C:\temp | Measure-Object).Count -eq 0)
{
    #Folder Empty
}
Denis Besic
  • 3,067
  • 3
  • 24
  • 35
4

It's a waste to get all files and directories and count them only to determine if directory is empty. Much better to use .NET EnumerateFileSystemInfos

$directory = Get-Item -Path "c:\temp"
if (!($directory.EnumerateFileSystemInfos() | select -First 1))
{
    "empty"
}
Michael Logutov
  • 2,551
  • 4
  • 28
  • 32
  • This is the right answer because it does account for hidden (and possibly system) files. – mark Jun 17 '22 at 03:24
3

Simple approach

if (-Not (Test-Path .\temp*))
{
  # do your stuff here
}

you can remove -Not if you want to enter the 'if' when files are present.

Clinton Ward
  • 2,441
  • 1
  • 22
  • 26
3

You can use the method .GetFileSystemInfos().Count to check the count of directories. Microsoft Docs

$docs = Get-ChildItem -Path .\Documents\Test
$docs.GetFileSystemInfos().Count
Alex_P
  • 2,580
  • 3
  • 22
  • 37
2
#Define Folder Path to assess and delete
$Folder = "C:\Temp\Stuff"

#Delete All Empty Subfolders in a Parent Folder
Get-ChildItem -Path $Folder -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse

#Delete Parent Folder if empty
If((Get-ChildItem -Path $Folder -force | Select-Object -First 1 | Measure-Object).Count -eq 0) {Remove-Item -Path $CATSFolder -Force -Recurse}
Filburt
  • 17,626
  • 12
  • 64
  • 115
  • You can get serious problems here, if you use `-Path $_.FullName` in Get-ChildItem. Pleaase use [-LiteralPath](https://stackoverflow.com/questions/33721892/is-get-childitem-recurse-broken-when-there-are-square-brackets-in-the-input-pat/55367757#55367757) !!! – it3xl Jun 24 '19 at 20:51
1

Just adding to JPBlanc, if directory path is $DirPath, this code also works for paths including square bracket characters.

    # Make square bracket non-wild card char with back ticks
    $DirPathDirty = $DirPath.Replace('[', '`[')
    $DirPathDirty = $DirPathDirty.Replace(']', '`]')

    if (Test-Path -Path "$DirPathDirty\*") {
            # Code for directory not empty
    }
    else {
            # Code for empty directory
    }
Atiq Rahman
  • 680
  • 6
  • 24
1
#################################################
# Script to verify if any files exist in the Monitor Folder
# Author Vikas Sukhija 
# Co-Authored Greg Rojas
# Date 6/23/16
#################################################


################Define Variables############ 
$email1 = "yourdistrolist@conoso.com" 
$fromadd = "yourMonitoringEmail@conoso.com" 
$smtpserver ="mailrelay.conoso.com" 

$date1 = get-date -Hour 1 -Minute 1 -Second 1
$date2 = get-date -Hour 2 -Minute 2 -Second 2 

###############that needs folder monitoring############################ 


$directory = "C:\Monitor Folder"

$directoryInfo = Get-ChildItem $directory | Measure-Object
$directoryInfo.count


if($directoryInfo.Count -gt '0') 
{ 

#SMTP Relay address 
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer) 

#Mail sender 
$msg.From = $fromadd 
#mail recipient 
$msg.To.Add($email1) 
$msg.Subject = "WARNING : There are " + $directoryInfo.count + " file(s) on " + $env:computername +  " in " + " $directory 
$msg.Body = "On " + $env:computername + " files have been discovered in the " + $directory + " folder."
$smtp.Send($msg) 

} 

Else
      { 
    Write-host "No files here" -foregroundcolor Green 
      } 
G Rojas
  • 35
  • 8
  • 3
    While I certainly want to encourage you to post on StackOverflow, G, there are several "best practices" that you are ignoring, intentionally or otherwise. (a) Generally, you should not just post code without explanation. (b) You should not re-post the same answer given by someone else (yours has been given at least twice if you scroll through the answers here). (c) You should not include a whole bunch of unrelated code--90% of your code is irrelevant to the question asked. I'm not going to downvote, but just wanted you to be prepared in case you see some downvotes come along. – Michael Sorens Jun 24 '16 at 01:07
1

Example of removing empty folder:

IF ((Get-ChildItem "$env:SystemDrive\test" | Measure-Object).Count -eq 0) {
    remove-Item "$env:SystemDrive\test" -force
}
Maciej Treder
  • 11,866
  • 5
  • 51
  • 74
Maciej
  • 21
  • 2
1
    $contents = Get-ChildItem -Path "C:\New folder"
    if($contents.length -eq "") #If the folder is empty, Get-ChileItem returns empty string
    {
        Remove-Item "C:\New folder"
        echo "Empty folder. Deleted folder"
    }
    else{
    echo "Folder not empty"
    }
Yash
  • 11
  • 2
1

One line for piping, by also using the GetFileSystemInfos().Count with a test :

gci -Directory | where { !@( $_.GetFileSystemInfos().Count) } 

will show all directories which have no items. Result:

Directory: F:\Backup\Moving\Test

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         5/21/2021   2:53 PM                Test [Remove]
d-----         5/21/2021   2:53 PM                Test - 1   
d-----         5/21/2021   2:39 PM                MyDir [abc]
d-----         5/21/2021   2:35 PM                Empty

I post this because I was having edge-case issues with names that contained brackets [ ]; failure was when using other methods and the output piped to Remove-Item missed the directory names with brackets.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
0

Getting a count from Get-ChildItem can provide false results because an empty folder or error accessing a folder could result in a 0 count.

The way I check for empty folders is to separate out errors:

Try { # Test if folder can be scanned
   $TestPath = Get-ChildItem $Path -ErrorAction SilentlyContinue -ErrorVariable MsgErrTest -Force | Select-Object -First 1
}
Catch {}
If ($MsgErrTest) { "Error accessing folder" }
Else { # Folder can be accessed or is empty
   "Folder can be accessed"
   If ([string]::IsNullOrEmpty($TestPath)) { # Folder is empty
   "   Folder is empty"
   }
}

The above code first tries to acces the folder. If an error occurs, it outputs that an error occurred. If there was no error, state that "Folder can be accessed", and next check if it's empty.

0

After looking into some of the existing answers, and experimenting a little, I ended up using this approach:

function Test-Dir-Valid-Empty {
    param([string]$dir)
    (Test-Path ($dir)) -AND ((Get-ChildItem -att d,h,a $dir).count -eq 0)
}

This will first check for a valid directory (Test-Path ($dir)). It will then check for any contents including any directories, hidden file, or "regular" files** due to the attributes d, h, and a, respectively.

Usage should be clear enough:

PS C_\> Test-Dir-Valid-Empty projects\some-folder
False 

...or alternatively:

PS C:\> if(Test-Dir-Valid-Empty projects\some-folder){ "empty!" } else { "Not Empty." }
Not Empty.

** Actually I'm not 100% certain what the defined effect of of a is here, but it does in any case cause all files to be included. The documentation states that ah shows hidden files, and I believe as should show system files, so I'm guessing a on it's own just shows "regular" files. If you remove it from the function above, it will in any case find hidden files, but not others.

Kjartan
  • 18,591
  • 15
  • 71
  • 96