I have a folder whose entire entire contents I want to delete, but I want to keep the actual folder. I have tried this:
function deleteFiles {
# The parameter.
param([string]$sourceDir)
# Move the files
Get-ChildItem -Path $sourceDir -Include *.* -Recurse | foreach { $_.Delete()}
#Delete empty directories
Get-ChildItem -Path $sourceDir -recurse | Where-Object {
$_.PSIsContainer -eq $true -and (Get-ChildItem -Path $_.FullName) -eq $null
} | Remove-Item
}
However as one of the subdirectories has its own sub directories they aren't deleted.
This should suffice:
Remove-Item -Path "$sourceDir\*" -Recurse
Related
I'm trying to use powershell to copy some directories where name match with filter.
First of all I delete all the directories that match in the destination path, alfter I try to copy source directories and contents but I've a problem because are copied only files inside directories and subdirectories and not the directories names and structures.
$source="F:\origin"
$destination="F:\dest"
$filter="#"
# Remove dirs #
Get-ChildItem -Path $destination -Recurse |
Where-Object { $_.DirectoryName -match $filter } |
remove-item -Recurse
# Copy dirs and all contents
Get-ChildItem -Path $source -Recurse |
Where-Object { $_.DirectoryName -match $filter } |
Copy-Item -Destination $destination
How can I do This ?
Thank you
EDIT
F:\origin\#test\index.php
F:\origin\#test1\index1.php
F:\origin\#test1\sub1\subindex1.php
F:\origin\no_consider\index1.php
Expected output
F:\dest\#test\index.php
F:\dest\#test1\index1.php
F:\dest\#test1\sub1\subindex1.php
a couple small tweaks seems to have done the trick. replaced some double quotes with single quotes, added a Recurse at the end of the one line and change DirectoryName to Name for the first one.
LEt me know if this works:
$source='c:\origin'
$destination='c:\dest'
$filter="#"
# Remove dirs #
Get-ChildItem -Path $destination -Recurse |
Where-Object { $_.Name -match $filter } |
remove-item -Recurse
# Copy dirs and all contents
Get-ChildItem -Path $source |
Where-Object { $_.Name -match $filter } |
Copy-Item -Destination $destination -Recurse -Force
I am working on some PowerShell script that automatically moves folders and files from the 'X-Drive' folder and move it into the 'Old' folder which also is inside the 'X-Drive' folder, but I want it to keep the first layer folders only, all what's inside can be moved but only the folder needs to be kept, but it also needs to be in the 'Old' folder.
$exclude = #('Keep 1', 'Keep 2')
Get-ChildItem -Path "C:\X-Drive" -Recurse -Exclude $exclude |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-0) } |
Move-Item -Destination "C:\X-Drive\Old" -ErrorAction 'SilentlyContinue'
Enumerate the subfolders of C:\X-D_rive, then move their content to corresponding subfolders in C:\X-Drive\old, e.g. like this:
$refdate = (Get-Date).AddDays(-1)
Get-ChildItem 'C:\X-Drive' -Directory -Exclude $exclude | ForEach-Object {
$dst = Join-Path 'C:\X-Drive\old' $_.Name
If (-not (Test-Path -LiteralPath $dst)) {
New-Item -Type Directory -Path $dst | Out-Null
}
Get-ChildItem $_.FullName -Recurse | Where-Object {
$_.LastWriteTime -lt $refdate
} | Move-Item -Destination $dst
}
You may want to add old to $excludes, BTW.
The code assumes you're running PowerShell v3 or newer.
I'm having problems to create a PS command that allows me to delete several subfolders without deleting the roof folder.
I.E:
C:\Test has many subfolders:
C:\Test\Item1
C:\Test\Item2
C:\Test\Item3
And the folders Item1, Item2 and Item3 have many subfolders and files.
I would like to create a PS that would allow me to delete all the empty subfolders inside Item1, Item2 and Item3 without deleting Item1, Item2 and Item3 folders. It is possible that any of the Item folders is empty, but I don't want to delete them, just the empty content of each folder.
This is just an example, I have a have around 300 Item folders inside Test.
I usually would use this:
$path="C:\TEST"
do {
$dir = gci $path -directory -recurse | Where { (gci $_.fullName).count -eq 0 } | select -expandproperty FullName
$dir | Foreach-Object { Remove-Item $_ }
} while ($dir.count -gt 0)
But this deletes the folder root folder (Item1, Item2 or Item3) if they are empty.
Thanks in advance.
So you are looking to delete All Items inside Empty Subfolders or all items in General?
This will delete all Folders or Items in General inside of the Directory "C:\abc\"
$path = "C:\abc\"
Get-ChildItem -Path $path -Recurse| Foreach-object {Remove-item -Recurse -path $_.FullName }
This will delete all Folders that dont have any items in them.
$path = "C:\abc\"
Get-ChildItem -Path $path -Recurse | Where-Object {(Get-ChildItem $_.FullName).Count -eq 0} |Foreach-object {Remove-item -Recurse -path $_.FullName }
ยด
This will look inside "C:\abc\" Get all the children and delete all empty Directories inside the Children in your example this would be Item1,Item2,...
$Path = "C:\abc\"
$itemFolders= Get-ChildItem -Path $Path
$itemFolders| Foreach-Object {
Get-ChildItem -Path $_.FullName |
Where-Object {(Get-ChildItem $_.FullName).Count -eq 0} |
Foreach-object {Remove-item -Recurse -path $_.FullName }
}
Just a quick and dirty bit of Code as I dont have much time, hope I could be of help.
EDIT: Here is what i came up with, its not as performant as I'd like but it gets the job done and is fairly quick, try it out for yourself it worked for me - even threw in a couple of comments and output to clarify what's going on.
$Path="C:\abc\"
$itemFolders = Get-ChildItem $Path
#Get All Folders inside
$AllFolders = $itemFolders | Get-ChildItem -Recurse | Where-Object {$_.PSIsContainer} | Select -Property FullName
#First delete all files older than 30 days
$itemFolders | Get-ChildItem -Recurse -File | ForEach-Object{
$limit = (Get-Date).AddDays(-30)
if($_.LastWriteTime -lt $limit)
{
"{0} hasn't been modified in the last 30 days deleting it" -f $_.FullName
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue
}
}
#Check if there are files inside that are not containers
$AllFolders | ForEach-Object{
$files = Get-ChildItem -File -Recurse -Path $_.FullName
$directories = Get-ChildItem -Directory -Recurse -Path $_.FullName
#If There are any files inside the folder dont delete it.
if($files.Count -gt 0)
{
"Found {0} files inside {1} do not delete this" -f $files.Count, $_.FullName
}
#If There are no files and no directories inside delete it.
elseif($files.Count -eq 0 -and $directories.Count -eq 0)
{
"Empty Folder {0} deleting it" -f $_.FullName
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
#If there are no files and empty directories inside delete it.
elseif($files.Count -eq 0 -and $directories.Count -gt 0)
{
"No Files but directories found in {0} since its recursive delete it" -f $_.FullName
Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
I have subfolders, and subsubfolders. In the subsubfolders, I want to find all subfolders without a file named PKA.dump. Can this be done in powershell?
The subfolders go from Angle1, Angle2, etc up to Angle24
The subsubfolders go from 1eV, 2eV, to 150eV.
I can find when they are less than a certain size:
Get-Childitem -path . -filter "PKA.dump" -recurse | where {$_.Length -le 500}
But what if they dont exist?
If you have just 2 levels of directories, don't recurse. Do something like this instead:
Get-ChildItem -Path . -Directory | Get-ChildItem -Directory | ? {
-not (Test-Path -LiteralPath (Join-Path $_.FullName 'PKA.dump'))
}
For a deeper folder structure this should be ok:
Get-ChildItem -Path C:\yourpath\ -recurse | where {$_.psiscontainer} | % {
if((Get-ChildItem -Path $_.FullName -File).name -notcontains "pka.dump"){ $_.FullName }
}
I'm trying to move all items except a certain type of file. In this case *.msg. It does fine if the excluded file resides within the parent folder. However, the moment that same type of file is located within a subdirectory, it fails to leave the file in place and instead moves it to the new location.
username = Get-Content '.\users.txt'
foreach ($un in $username)
{
$destA = "c:\users\$un\redirectedfolders\mydocuments"
$destB = "c:\users\$un\redirectedfolders\desktop"
$sourceA = "C:\users\$un\mydocuments"
$sourceB = "C:\users\$un\desktop"
New-Item -ItemType Directory -Path $destA, $destB
Get-ChildItem $sourceA -Exclude '*.msg' -Recurse | Move-Item -Destination {Join-Path $destA $_.FullName.Substring($sourceA.length)}
Get-ChildItem $sourceB -Exclude '*.msg' -Recurse | Move-Item -Destination {Join-Path $destB $_.FullName.Substring($sourceB.length)}
}
This is due to the filtering done by the Get-ChildItem exclude filter. It's kind of a known issue, and if you really want I could probably dig up some reference documentation, but it may take some time. Regardless, GCI doesn't handle wildcards very well when it comes to filtering things. What you are probably better off doing is piping it to a Where command like this:
$username = Get-Content '.\users.txt'
foreach ($un in $username)
{
$destA = "c:\users\$un\redirectedfolders\documents"
$destB = "c:\users\$un\redirectedfolders\desktop"
$sourceA = "C:\users\$un\documents"
$sourceB = "C:\users\$un\desktop"
New-Item -ItemType Directory -Path $destA, $destB
GCI $sourceA -recurse | ?{$_.Extension -ne ".msg" -and !$_.PSIsContainer} | %{
$CurDest = Join-Path $destA $_.FullName.Substring($sourceA.length)
If(!(Test-Path $CurDest.SubString(0,$CurDest.LastIndexOf("\")))){New-Item -Path $CurDest -ItemType Directory|Out-Null}
$_ | Move-Item -Destination $CurDest
}
GCI $sourceB -recurse | ?{$_.Extension -ne ".msg" -and !$_.PSIsContainer} | %{
$CurDest = Join-Path $destB $_.FullName.Substring($sourceB.length)
If(!(Test-Path $CurDest.SubString(0,$CurDest.LastIndexOf("\")))){New-Item -Path $CurDest -ItemType Directory|Out-Null}
$_ | Move-Item -Destination $CurDest
}
}
Edit: Ok, now excludes folders, and also keeps folder structure.
Edit2: Re-designed to do a ForEach loop on the files, build the destination path as $CurDest, test to make sure it exists and make it if it doesn't, then move the files. Also changed mydocuments to documents which is the path to a user's My Documents folder.