Move Files Containing X in their Names to Folder X - powershell

I'm Trying to move files containing "Sxx" in their names to folder named "Sxx".
for example:
file1: S01E12.srt ----> /S01/S01E12.srt
file2: S03E14.jpg ----> /S03/S03E14.jpg
etc.
So i came up with these codes for creating folders using files having "Sxx" in their names and then moving them into the right folders.
For creating folders:
foreach ($name in (Get-ChildItem -File | % {$_.BaseName -replace 'E\d{2}',''}))
{
if ($name -like 'S*') {
New-Item -path "$name" -ItemType Directory
}
}
For moving files:
get-childitem -File | where {$_ -like "S01*"} | move-Item -Destination "S01*"
get-childitem -File | where {$_ -like "S02*"} | move-Item -Destination "S02*"
...
etc.
Any idea how to replace hardcoding method for moving part?
If you have any advice or better code for any part that would be awesome too.

Below is my code. I created two foreach loops to go once through all files and afterwards through all folders. I used a substring to get part of the file names.
$files = Get-ChildItem -File -Path C:\users\Lenovo\Desktop\Test
$dir = Get-ChildItem -Path C:\users\lenovo\Desktop\Test -Directory
foreach ($item in $files) {
foreach ($folder in $dir)
{
if (($item.Name).Substring(0,3) -like $folder.Name)
{
Move-Item -Path $item.FullName -Destination $folder.FullName
}
}
}
I create four files with S01.txt to S04.txt and it was working. To test whether your variable is empty, either you can write the variable with Write-Host or slightly more advanced, you can use the debug mode to see exactly what your variables contain.

Related

Excluding Folders with Get-ChildItem - Need Help Debugging a Script

I've searched through both StackOverflow and SuperUser to try to figure this out, and I'm still getting plagued by a problem I can't figure out how to fix. I know it's something simple, but after playing with it for an hour I'm still stumped. Simple question: how the heck do I tell Get-Childitem to exclude folders?
Right up front here's the code that doesn't work:
$sourceDir="E:\Deep Storage"
$targetDir="W:\Deep Storage"
$excludeThese = 'Projects2','Projects3','Projects4';
Get-ChildItem -Path $sourceDir -Directory -Recurse |
where {$_.fullname -notin $excludeThese} |
Get-ChildItem -Path $sourceDir | ForEach-Object {
$num=1
$nextName = Join-Path -Path $targetDir -ChildPath $_.name
while(Test-Path -Path $nextName)
{
$nextName = Join-Path $targetDir ($_.BaseName + "_$num" + $_.Extension)
$num+=1
}
$_ | Move-Item -Destination $nextName -Force -Verbose -WhatIf
}
}
The underlying concept here already works:
$sourceDir="E:\Deep Storage"
$targetDir="W:\Deep Storage"
Get-ChildItem -Path $sourceDir -File -Recurse | ForEach-Object {
$num=1
$nextName = Join-Path -Path $targetDir -ChildPath $_.name
while(Test-Path -Path $nextName)
{
$nextName = Join-Path $targetDir ($_.BaseName + "_$num" + $_.Extension)
$num+=1
}
$_ | Copy-Item -Destination $nextName -Verbose
}
Basically what this does is it moves folders from one place to another, and if files exist in both places, it renames files coming in. It helps keep my archive drive clear. But there are three folders there that I want to exclude because I still pull assets from them regularly, so I don't need those files moved.
Hence the difference between the two code samples: in the first one, I'm trying to get Get-Childitem to exclude a specific trio of folders, while this second one just grabs everything all at once.
I tried just doing a straight -Exclude with $excludeThese as the variable, without success; I tried skipping the variable approach altogether and just putting the folder names in after -Exclude. Still didn't work. I also tried putting in the entire path to the folders I wanted to exclude. No good--no matter what I did, the -WhatIf showed that the script was trying to move everything, including the folders I was theoretically excluding.
The last trick I tried was one I came across here on SO, and that was to go a gci with the exclude argument first, then do another gci after it. That still failed, so now I have to turn to the experts for help.
I would use a regex string created from the (escaped) directory names to exclude to make sure files withing these folders are ignored.
Also, by using a lookup Hashtable of all file names already present in the target folder, figuring out if a file with a certain name already exists is extremely fast.
$sourceDir = 'E:\Deep Storage'
$targetDir = 'W:\Deep Storage'
$excludeThese = 'Projects2','Projects3','Projects4';
# create a regex string with all folder names to exclude combined with regex OR (|)
$excludeDirs = ($excludeThese | ForEach-Object { [Regex]::Escape($_) }) -join '|'
# create a lookup Hashtable and store the filenames already present in the destination folder
$existingFiles = #{}
Get-ChildItem -Path $targetDir -File | ForEach-Object { $existingFiles[$_.Name] = $true }
Get-ChildItem -Path $sourceDir -File -Recurse |
Where-Object {$_.DirectoryName -notmatch $excludeDirs} |
ForEach-Object {
# construct the new filename by appending an index number if need be
$newName = $_.Name
$count = 1
while ($existingFiles.ContainsKey($newName)) {
$newName = "{0}_{1}{2}" -f $_.BaseName, $count++, $_.Extension
}
# add this new name to the Hashtable so it exists in the next run
$existingFiles[$newName] = $true
# use Join-Path to create a FullName for the file
$newFile = Join-Path -Path $targetDir -ChildPath $newName
$_ | Move-Item -Destination $newFile -Force -Verbose -WhatIf
}
Assuming the excluded directories are at the top:
$sourceDir="E:\Deep Storage"
$excludeThese = 'Projects2','Projects3','Projects4'
get-childitem $sourcedir -exclude $excludethese | get-childitem -recurse

How to rename files and folders recursively?

I have this PowerShell code which goes through a folder and creates a list of all files and subfolders in the folder and renames them for me (replacing spaces with underscores). The code both works and doesn't work:
$myFiles = Get-ChildItem -Path "\\folder path" -include "* *" -recurse
foreach ($file in $myFiles)
{
$newFileName=$file.Name.Replace(" ","_")
Rename-Item $file $newFileName
}
The code successfully renames all the subfolders and files in the original folder, but then it looks for the subfolder which no longer exists (because the spaces were changed to dashes), and creates the error
Get-ChildItem: Cannot find path '\\folder path' because it does not exist.
This code will work if I run it multiple times, until I stop getting errors. Each time I run it, it goes one subfolder level deeper until there are no more subfolders to rename. So, I get the desired result in the end, but is there a way to make this code work by starting with the lowest nested files, or any other method not requiring me to run the same code multiple times?
A Stack<T> (last-in-first-out) should work for this case. I added a -WhatIf switch to Rename-Item so you can confirm that the code is doing what you feel is right, you may remove it after.
using namespace System.IO
using namespace System.Collections.Generic
$stack = [Stack[FileSystemInfo]]::new()
[DirectoryInfo] $path = "\\folder path"
foreach($entry in $path.EnumerateFileSystemInfos('*', 'AllDirectories')) {
$stack.Push($entry)
}
while($stack.Count) {
$entry = $stack.Pop()
if(-not $entry.Name.Contains(' ')) {
continue
}
$name = $entry.Replace(' ', '_')
Rename-Item -LiteralPath $entry.FullName -NewName $name -WhatIf
}
Here is how I thought of doing it. I iterated through all files first because there is no folder dependencies to rename those. Then I iterated through all folders and put the folders in reverse and renamed them all. Seems to work.
$myFiles = Get-ChildItem -Path 'E:\Data\test folder' -include "* *" -recurse | Where {$_.PSIsContainer -eq $false}
$myFiles
foreach ($file in $myFiles)
{
$newFileName=$file.Name.Replace(" ","_")
Rename-Item $file $newFileName
}
Get-ChildItem -Path 'E:\Data\test folder' -recurse
$myfolders = Get-ChildItem -Path 'E:\Data\test folder' -include "* *" -recurse | Where {$_.PSIsContainer -eq $True} | Sort-Object -Descending
$myfolders.FullName
foreach ($folder in $myfolders)
{
$newFolderName=$folder.Name.Replace(" ","_")
Rename-Item $folder $newFolderName
}
Get-ChildItem -Path 'E:\Data\test folder' -recurse -directory

Moving Files based on filename

Im looking to move files based on the last half of the filename. Files look like this
43145123_Stuff.zip
14353135_Stuff.zip
2t53542y_Stuff.zip
422yg3hh_things.zip
I am only looking to move files that end in Stuff.zip
I have this in PowerShell so far but it only will move files according to the first half of a file name.
#set Source and Destination folder location
$srcpath = "C:\Powershelltest\Source"
$dstpath = "C:\Powershelltest\Destination"
#Set the files name which need to move to destination folder
$filterLists = #("stuff.txt","things")
#Get all the child file list with source folder
$fileList = Get-ChildItem -Path $srcpath -Force -Recurse
#loop the source folder files to find the match
foreach ($file in $fileList)
{
#checking the match with filterlist
foreach($filelist in $filterLists)
{
#$key = $file.BaseName.Substring(0,8)
#Spliting value before "-" for matching with filterlists value
$splitFileName = $file.BaseName.Substring(0, $file.BaseName.IndexOf('-'))
if ($splitFileName -in $filelist)
{
$fileName = $file.Name
Move-Item -Path $($file.FullName) -Destination $dstpath
}
}
}
There seems to be some differences between the state goal and what the code actually does. This will move the files to the destination directory. When you are confident that the files will be moved correctly, remove the -WhatIf from the Move-Item command.
$srcpath = "C:\Powershelltest\Source"
$dstpath = "C:\Powershelltest\Destination"
Get-ChildItem -File -Recurse -Path $srcpath |
ForEach-Object {
if ($_.Name -match '.*Stuff.zip$') {
Move-Item -Path $_.FullName -Destination $dstpath -WhatIf
}
}
Actually this can be written in PowerShell very efficiently (I hope I got the details right, let me know):
Get-ChildItem $srcpath -File -Force -Recurse |
where { ($_.Name -split "_" | select -last 1) -in $filterLists } |
Move-Item $dstpath
Alternatively, if you only want to look for this one particular filter, you can specify that directly, using wildcards:
Get-ChildItem $srcpath -Filter "*_Stuff.zip"

How to copy files using a txt list to define beginning of file names

Hello awesome community :)
I have a list containing a bunch of SKU's. All the filenames of the files, that I need to copy to a new location, starts with the corresponding SKU like so
B6BC004-022_10_300_f.jpg
In this case "B6BC004" is the SKU and my txt list contains "B6BC004" along with many other SKU's.
Somewhere in the code below I know I have to define that it should search for files beginning with the SKU's from the txt file but I have no idea how to define it.
Get-Content .\photostocopy.txt | Foreach-Object { copy-item -Path $_ -Destination "Z:\Photosdestination\"}
Thanks in advance :)
If all files start with one of the SKU's, followed by a dash like in your example, this should work:
$sourceFolder = 'ENTER THE PATH WHERE THE FILES TO COPY ARE'
$destination = 'Z:\Photosdestination'
# get an array of all SKU's
$sku = Get-Content .\photostocopy.txt | Select-Object -Unique
# loop through the list of files in the source folder and copy all that have a name beginning with one of the SKU's
Get-ChildItem -Path $sourceFolder -File -Recurse |
Where-Object { $sku -contains ($_.Name -split '\s*-')[0] } |
ForEach-Object { $_ | Copy-Item -Destination $destination }
I haven't tested this so please proceed with caution!
What is does it loops through all the items in your photostocopy.txt file, searches the $source location for a file(s) with a name like the current item from your file. It then checks if any were found before outputting something to the console and possibly moving the file(s).
$source = '#PATH_TO_SOURCE'
$destination = '#PATH_TO_DESTINATION'
$photosToCopy = Get-Content -Path '#PATH_TO_TXT_FILE'
$photosToCopy | ForEach-Object{
$filesToCopy = Get-ChildItem -Path $source -File | Where-Object {$_.Name -like "$_*"}
if ($fileToCopy.Count -le 0){
Write-Host "No files could be found for: " $_
}else{
$filesToCopy | ForEach-Object{
Write-Host "Moving: " $_.Name
Copy-Item -Path $_.FullName -Destination $destination
}
}
}
Let me know how if this helps you :)

How to recursively remove all empty folders in PowerShell?

I need to recursively remove all empty folders for a specific folder in PowerShell (checking folder and sub-folder at any level).
At the moment I am using this script with no success.
Could you please tell me how to fix it?
$tdc='C:\a\c\d\'
$a = Get-ChildItem $tdc -recurse | Where-Object {$_.PSIsContainer -eq $True}
$a | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
I am using PowerShell on Windows 8.1 version.
You need to keep a few key things in mind when looking at a problem like this:
Get-ChildItem -Recurse performs head recursion, meaning it returns folders as soon as it finds them when walking through a tree. Since you want to remove empty folders, and also remove their parent if they are empty after you remove the empty folders, you need to use tail recursion instead, which processes the folders from the deepest child up to the root. By using tail recursion, there will be no need for repeated calls to the code that removes the empty folders -- one call will do it all for you.
Get-ChildItem does not return hidden files or folders by default. As a result you need to take extra steps to ensure that you don't remove folders that appear empty but that contain hidden files or folders. Get-Item and Get-ChildItem both have a -Force parameter which can be used to retrieve hidden files or folders as well as visible files or folders.
With those points in mind, here is a solution that uses tail recursion and that properly tracks hidden files or folders, making sure to remove hidden folders if they are empty and also making sure to keep folders that may contain one or more hidden files.
First this is the script block (anonymous function) that does the job:
# A script block (anonymous function) that will remove empty folders
# under a root folder, using tail-recursion to ensure that it only
# walks the folder tree once. -Force is used to be able to process
# hidden files/folders as well.
$tailRecursion = {
param(
$Path
)
foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $Path -Directory) {
& $tailRecursion -Path $childDirectory.FullName
}
$currentChildren = Get-ChildItem -Force -LiteralPath $Path
$isEmpty = $currentChildren -eq $null
if ($isEmpty) {
Write-Verbose "Removing empty folder at path '${Path}'." -Verbose
Remove-Item -Force -LiteralPath $Path
}
}
If you want to test it here's code that will create interesting test data (make sure you don't already have a folder c:\a because it will be deleted):
# This creates some test data under C:\a (make sure this is not
# a directory you care about, because this will remove it if it
# exists). This test data contains a directory that is hidden
# that should be removed as well as a file that is hidden in a
# directory that should not be removed.
Remove-Item -Force -Path C:\a -Recurse
New-Item -Force -Path C:\a\b\c\d -ItemType Directory > $null
$hiddenFolder = Get-Item -Force -LiteralPath C:\a\b\c
$hiddenFolder.Attributes = $hiddenFolder.Attributes -bor [System.IO.FileAttributes]::Hidden
New-Item -Force -Path C:\a\b\e -ItemType Directory > $null
New-Item -Force -Path C:\a\f -ItemType Directory > $null
New-Item -Force -Path C:\a\f\g -ItemType Directory > $null
New-Item -Force -Path C:\a\f\h -ItemType Directory > $null
Out-File -Force -FilePath C:\a\f\test.txt -InputObject 'Dummy file'
Out-File -Force -FilePath C:\a\f\h\hidden.txt -InputObject 'Hidden file'
$hiddenFile = Get-Item -Force -LiteralPath C:\a\f\h\hidden.txt
$hiddenFile.Attributes = $hiddenFile.Attributes -bor [System.IO.FileAttributes]::Hidden
Here's how you use it. Note that this will remove the top folder (the C:\a folder in this example, which gets created if you generated the test data using the script above) if that folder winds up being empty after deleting all empty folders under it.
& $tailRecursion -Path 'C:\a'
You can use this:
$tdc="C:\a\c\d"
$dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName
$dirs | Foreach-Object { Remove-Item $_ }
$dirs will be an array of empty directories returned from the Get-ChildItem command after filtering. You can then loop over it to remove the items.
Update
If you want to remove directories that contain empty directories, you just need to keep running the script until they're all gone. You can loop until $dirs is empty:
$tdc="C:\a\c\d"
do {
$dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName
$dirs | Foreach-Object { Remove-Item $_ }
} while ($dirs.count -gt 0)
If you want to ensure that hidden files and folders will also be removed, include the -Force flag:
do {
$dirs = gci $tdc -directory -recurse | Where { (gci $_.fullName -Force).count -eq 0 } | select -expandproperty FullName
$dirs | Foreach-Object { Remove-Item $_ }
} while ($dirs.count -gt 0)
Get-ChildItem $tdc -Recurse -Force -Directory |
Sort-Object -Property FullName -Descending |
Where-Object { $($_ | Get-ChildItem -Force | Select-Object -First 1).Count -eq 0 } |
Remove-Item -Verbose
The only novel contribution here is using Sort-Object to reverse sort by the directory's FullName. This will ensure that we always process children before we process parents (i.e., "tail recursion" as described by Kirk Munro's answer). That makes it recursively remove empty folders.
Off hand, I'm not sure if the Select-Object -First 1 will meaningfully improve performance or not, but it may.
Just figured I would contribute to the already long list of answers here.
Many of the answers have quirks to them, like needing to run more than once. Others are overly complex for the average user (like using tail recursion to prevent duplicate scans, etc).
Here is a very simple one-liner that I've been using for years, and works great...
It does not account for hidden files/folders, but you can fix that by adding -Force to the Get-ChildItem command
This is the long, fully qualified cmdlet name version:
Get-ChildItem -Recurse -Directory | ? { -Not ($_.EnumerateFiles('*',1) | Select-Object -First 1) } | Remove-Item -Recurse
So basically...here's how it goes:
Get-ChildItem -Recurse -Directory - Start scanning recursively looking for directories
$_.EnumerateFiles('*',1) - For each directory...Enumerate the files
EnumerateFiles will output its findings as it goes, GetFiles will output when it is done....at least, that's how it is supposed to work in .NET...for some reason in PowerShell GetFiles starts spitting out immediately. But I still use EnumerateFiles because in testing it was reliably faster.
('*',1) means find ALL files recursively.
| Select-Object -First 1 - Stop at the first file found
This was difficult to test how much it helped. In some cases it helped tremendously, other times it didn't help at all, and in some cases it slowed it down by a small amount. So I really don't know. I guess this is optional.
| Remove-Item -Recurse - Remove the directory, recursively (ensures directories that contain empty sub directories gets removed)
If you're counting characters, this could be shortened to:
ls -s -ad | ? { -Not ($_.EnumerateFiles('*',1) | select -First 1) } | rm -Recurse
-s - alias for -Recurse
-ad - alias for -Directory
If you really don't care about performance because you don't have that many files....even more so to:
ls -s -ad | ? {!($_.GetFiles('*',1))} | rm -Recurse
Side note:
While playing around with this, I started testing various versions with Measure-Command against a server with millions of files and thousands of directories.
This is faster than the command I've been using (above):
(gi .).EnumerateDirectories('*',1) | ? {-Not $_.EnumerateFiles('*',1) } | rm -Recurse
ls c:\temp -rec |%{ if ($_.PSIsContainer -eq $True) {if ( (ls $_.fullname -rec | measure |select -expand count ) -eq "0" ){ ri $_.fullname -whatif} } }
Assuming you're inside the parent folder of interest
gci . -Recurse -Directory | % { if(!(gci -Path $_.FullName)) {ri -Force -Recurse $_.FullName} }
For your case with $tdc it'll be
gci $tdc -Recurse -Directory | % { if(!(gci -Path $_.FullName)) {ri -Force -Recurse $_.FullName} }
If you just want to make sure, that you delete only folders that may contain subfolders but no files within itself and its subfolders, this may be an easier an quicker way.
$Empty = Get-ChildItem $Folder -Directory -Recurse |
Where-Object {(Get-ChildItem $_.FullName -File -Recurse -Force).Count -eq 0}
Foreach ($Dir in $Empty)
{
if (test-path $Dir.FullName)
{Remove-Item -LiteralPath $Dir.FullName -recurse -force}
}
Recursively removing empty subdirectories can also be accomplished using a "For Loop".
Before we start, let's make some subdirectories & text files to work with in $HOME\Desktop\Test
MD $HOME\Desktop\Test\0\1\2\3\4\5
MD $HOME\Desktop\Test\A\B\C\D\E\F
MD $HOME\Desktop\Test\A\B\C\DD\EE\FF
MD $HOME\Desktop\Test\Q\W\E\R\T\Y
MD $HOME\Desktop\Test\Q\W\E\RR
"Hello World" > $HOME\Desktop\Test\0\1\Text1.txt
"Hello World" > $HOME\Desktop\Test\A\B\C\D\E\Text2.txt
"Hello World" > $HOME\Desktop\Test\A\B\C\DD\Text3.txt
"Hello World" > $HOME\Desktop\Test\Q\W\E\RR\Text4.txt
First, store the following Script Block in the variable $SB. The variable can be called later using the &SB command. The &SB command will output a list of empty subdirectories contained in $HOME\Desktop\Test
$SB = {
Get-ChildItem $HOME\Desktop\Test -Directory -Recurse |
Where-Object {(Get-ChildItem $_.FullName -Force).Count -eq 0}
}
NOTE: The -Force parameter is very important. It makes sure that directories which contain hidden files and subdirectories, but are otherwise empty, are not deleted in the "For Loop".
Now use a "For Loop" to recursively remove empty subdirectories in $HOME\Desktop\Test
For ($Empty = &$SB ; $Empty -ne $null ; $Empty = &$SB) {Remove-Item (&$SB).FullName}
Tested as working on PowerShell 4.0
I have adapted the script of RichardHowells.
It doesn't delete the folder if there is a thumbs.db.
##############
# Parameters #
##############
param(
$Chemin = "" , # Path to clean
$log = "" # Logs path
)
###########
# Process #
###########
if (($Chemin -eq "") -or ($log-eq "") ){
Write-Error 'Parametres non reseignes - utiliser la syntaxe : -Chemin "Argument" -log "argument 2" ' -Verbose
Exit
}
#loging
$date = get-date -format g
Write-Output "begining of cleaning folder : $chemin at $date" >> $log
Write-Output "------------------------------------------------------------------------------------------------------------" >> $log
<########################################################################
define a script block that will remove empty folders under a root folder,
using tail-recursion to ensure that it only walks the folder tree once.
-Force is used to be able to process hidden files/folders as well.
########################################################################>
$tailRecursion = {
param(
$Path
)
foreach ($childDirectory in Get-ChildItem -Force -LiteralPath $Path -Directory) {
& $tailRecursion -Path $childDirectory.FullName
}
$currentChildren = Get-ChildItem -Force -LiteralPath $Path
Write-Output $childDirectory.FullName
<# Suppression des fichiers Thumbs.db #>
Foreach ( $file in $currentchildren )
{
if ($file.name -notmatch "Thumbs.db"){break}
if ($file.name -match "Thumbs.db"){
Remove-item -force -LiteralPath $file.FullName}
}
$currentChildren = Get-ChildItem -Force -LiteralPath $Path
$isEmpty = $currentChildren -eq $null
if ($isEmpty) {
$date = get-date -format g
Write-Output "Removing empty folder at path '${Path}'. $date" >> $log
Remove-Item -Force -LiteralPath $Path
}
}
# Invocation of the script block
& $tailRecursion -Path $Chemin
#loging
$date = get-date -format g
Write-Output "End of cleaning folder : $chemin at $date" >> $log
Write-Output "------------------------------------------------------------------------------------------------------------" >> $log
Something like this works for me. The script delete empty folders and folders containing only folder (no files, no hidden files).
$items = gci -LiteralPath E:\ -Directory -Recurse
$dirs = [System.Collections.Generic.HashSet[string]]::new([string[]]($items |% FullName))
for (;;) {
$remove = $dirs |? { (gci -LiteralPath $_ -Force).Count -eq 0 }
if ($remove) {
$remove | rm
$dirs.ExceptWith( [string[]]$remove )
}
else {
break
}
}
I wouldn't take the comments/1st post to heart unless you also want to delete files that are nested more than one folder deep. You are going to end up deleting directories that may contain directories that may contain files. This is better:
$FP= "C:\Temp\"
$dirs= Get-Childitem -LiteralPath $FP -directory -recurse
$Empty= $dirs | Where-Object {$_.GetFiles().Count -eq 0 **-and** $_.GetDirectories().Count -eq 0} |
Select-Object FullName
The above checks to make sure the directory is in fact empty whereas the OP only checks to make sure there are no files. That in turn would result in files nexted a few folders deep also being deleted.
You may need to run the above a few times as it won't delete Dirs that have nested Dirs. So it only deletes the deepest level. So loop it until they're all gone.
Something else I do not do is use the -force parameter. That is by design. If in fact remove-item hits a dir that is not empty you want to be prompted as an additional safety.
$files = Get-ChildItem -Path c:\temp -Recurse -Force | where psiscontainer ; [array]::reverse($files)
[Array]::reverse($files) will reverse your items, so you get the lowest files in hierarchy first.
I use this to manipulate filenames that have too long filepaths, before I delete them.
This is a simple approach
dir -Directory | ? { (dir $_).Count -eq 0 } | Remove-Item
This will remove up all empty folders in the specified directory $tdc.
It is also a lot faster since there's no need for multiple runs.
$tdc = "x:\myfolder" # Specify the root folder
gci $tdc -Directory -Recurse `
| Sort-Object { $_.FullName.Length } -Descending `
| ? { $_.GetFiles().Count -eq 0 } `
| % {
if ($_.GetDirectories().Count -eq 0) {
Write-Host " Removing $($_.FullName)"
$_.Delete()
}
}
#By Mike Mike Costa Rica
$CarpetasVacias = Get-ChildItem -Path $CarpetaVer -Recurse -Force -Directory | Where {(gci $_.fullName).count -eq 0} | select Fullname,Name,LastWriteTime
$TotalCarpetas = $CarpetasVacias.Count
$CountSu = 1
ForEach ($UnaCarpeta in $CarpetasVacias){
$RutaCarp = $UnaCarpeta.Fullname
Remove-Item -Path $RutaCarp -Force -Confirm:$False -ErrorAction Ignore
$testCar = Test-Path $RutaCarp
if($testCar -eq $true){
$Datem = (Get-Date).tostring("MM-dd-yyyy HH:mm:ss")
Write-Host "$Datem ---> $CountSu de $TotalCarpetas Carpetas Error Borrando Directory: $RutaCarp" -foregroundcolor "red"
}else{
$Datem = (Get-Date).tostring("MM-dd-yyyy HH:mm:ss")
Write-Host "$Datem ---> $CountSu de $TotalCarpetas Carpetas Correcto Borrando Directory: $RutaCarp" -foregroundcolor "gree"
}
$CountSu += 1
}