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 }
}
Related
I am doing some batch file name updates and am having trouble including folders. I have it currently set to target only specific file types, but I also want to include folders. Since folders don't have an extension I am unsure how to specify folders in the "-include" string. Any help would be greatly appreciated.
Here is what I am currently working with, but it ignores folders when I would like them included.
Get-ChildItem k:/toolbox/powershell -Include *.gif, *.jpg, *.png, *.xls,
*.xlsx, *.ppt, *.pptx, *.doc, *.docx, *.pdf -recurse | where {$_.name -match
"_"} | foreach {
$New=$_.name.Replace("_","-")
Rename-Item -path $_.Fullname -newname $New -passthru
}
(Get-Item '~\Desktop\*') | foreach { $FolderName = $_.name.Replace("_","-"); Rename-Item -path $_.fullname -newname $FolderName -passthru }
I would just add 2nd statement:
Get-ChildItem "k:/toolbox/powershell" -Recurse |where mode -eq d----- | where {$_.name -match "_"} | foreach {$New=$_.name.Replace("_","-")
Rename-Item -path $_.Fullname -newname $New -passthru }
If you run Get-ChildItem "k:/toolbox/powershell" you will receive a list of items where the "Mode" is "d-----" for directories, hence you can use that filter criteria for directories
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 a bunch of html files that I need to rename with url encoding before I upload them to the server. I've tried:
Get-ChildItem -Path c:\temp\ -Recurse -Filter *.html | Rename-Item -NewName { $_.Name.replace("*.html",[Web.Httputility]::UrlEncode("*.html")) }
But that doesn't apply the encoding, can this be even done somehow?
Here's a basic way to do it, based on this answer:
(Get-ChildItem -Path c:\temp\ -Recurse -Filter *.html -File) |
foreach { ren $_.fullname ([uri]::EscapeDataString($_))}
Originally I had written it without the () around the Get-ChildItem, but found it was still reading directory information while the rename had already renamed the first item. Then the rename reencoded the first item a second time, thus making it a bit munged up.
Here's a cleaner version that handles the files first and then folders:
$files = Get-ChildItem -Path c:\temp\ -Recurse -Filter *.html -File
$folders = Get-ChildItem -Path c:\temp\ -Recurse -Filter *.html -Directory
$files | foreach { ren $_.fullname ([uri]::EscapeDataString($_))}
$folders | foreach { ren $_.fullname ([uri]::EscapeDataString($_))}
Based on your answers i did this to make it work
(Get-ChildItem -Path c:\temp\ -Recurse -Filter *.html) |
foreach { ren $_.fullName ([uri]::EscapeDataString($_.Name))} | Out-Null
Get-ChildItem -Path c:\temp\ -Recurse | ?{ $_.PSIsContainer } |
foreach { ren $_.fullName ([uri]::EscapeDataString($_.Name))}
First I had to do only files and then folders, because when top folder gets renamed, then the path to files inside it doesn't exist any more.
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