I´m totally new to Powershell and wanted to write a script that deletes all non-mp3 files in a directory.
My solution:
get-childitem -Recurse |
Where-Object {!($_.PSIsContainer)} |
Where {$_.Extension -ne ".mp3"} |
remove-item
What can be improved in this statement or could be written in another way.
Are there any problems with this statement?
Thank you.
I would use just one Where-Object command:
Get-childitem -Recurse |
Where-Object {!$_.PSIsContainer -AND $_.Extension -ne '.mp3'} |
Remove-Item -whatIf
If you're certain that no directories have 'mp3' extension :
Get-childitem -Recurse | Where-Object {$_.Extension -ne '.mp3'} |
Remove-Item -whatIf
Remove -whatIf to delete the files.
Related
I create a PowerShell command that have to remove on my diskstation all files inside folders which contains the word "rendery". Everything would be fine, if the command deleted the files in the folder containing the word "rendery", because the script currently deletes the folder (along with the files that are inside) that contains the word "rendery".
Get-ChildItem C:\Test -Recurse | Where-Object {$_.PSIsContainer -eq $true -and $_.Name -match "rendery"} | Remove-Item -Recurse -Force
Insert another Get-ChildItem call after Where-Object to resolve only the child items of the target folders:
Get-ChildItem C:\Test -Recurse | Where-Object {$_.PSIsContainer -and $_.Name -match "rendery"} | Get-ChildItem | Remove-Item -Recurse -Force
Note that $_.PSIsContainer is already a boolean value, so you can shorten $_.PSIsContainer -eq $true to just $_.PSIsContainer
Hello and thanks in advance for the help. I am attempting to remove an extra extension that was added to documents in a library due to a security breach. When i manually remove the extension ".easy2lock" the file becomes available. However, when i try to do this programmatically via powershell it works, but not for folders with long paths. Does anyone know how to get around this in powershell?
I've tried tried updating my registry to allow long paths, however, i don't believe that has any affect on
here is the script and error i recieve:
[string]$DeleteBadExtension = ".easy2lock_read_me"
[string]$BadExtension = ".easy2lock"
Get-ChildItem -Filter "*$BadExtension" -Recurse | Rename-Item -NewName {$_.Name -replace $BadExtension, [string]::Empty}
Get-ChildItem *$DeleteBadExtension -Recurse | foreach { Remove-Item -Path $_.FullName }
I'll have to take your word for it that the files are usable after changing the name, that hasn't been my experience. To be able to access long paths in powershell you'll need to use the -LiteralPath parameter. Unfortunately the -Path parameter will be the default used when piping. -LiteralPath does take pipeline input by propertyname so you can either manipulate the object removing path and adding literal path like this
Get-ChildItem -Filter "*$BadExtension" -Recurse |
Select-Object Name,Basename,Extension,#{n='LiteralPath';e={"\\?\$($_.fullname)"}} |
Rename-Item -NewName {$_.Name -replace $BadExtension}
Or you can use a Foreach-Object or foreach loop and use the required syntax \\?\ for the path.
Get-ChildItem -Filter "*$BadExtension" -Recurse | Foreach-Object {
Rename-Item -LiteralPath "\\?\$($_.FullName)" -NewName ($_.Name -replace ‘$BadExtension’)
}
Edit
Since the basename is the desired filename (just without the unwanted extension) you can use the basename as the newname. All four examples have been tested and confirmed to work. If it's not working for you then there is something else going on.
Get-ChildItem -Filter *$BadExtension -Recurse | ForEach-Object {
Rename-Item -LiteralPath "\\?\$($_.FullName)" -NewName ($_.name -replace $BadExtension)
}
Get-ChildItem -Filter *$BadExtension -Recurse | ForEach-Object {
Rename-Item -LiteralPath "\\?\$($_.FullName)" -NewName $_.basename
}
Get-ChildItem -Filter "*$BadExtension" -Recurse |
Select-Object Name,#{n='LiteralPath';e={"\\?\$($_.fullname)"}} |
Rename-Item -NewName {$_.Name -replace $BadExtension}
Get-ChildItem -Filter "*$BadExtension" -Recurse |
Select-Object Basename,#{n='LiteralPath';e={"\\?\$($_.fullname)"}} |
Rename-Item -NewName {$_.baseName}
I have code I put together from different sources found online. That code, I believe, is supposed to search and find all folders who have no files/and whose subfolders have no files, then add the text "NA -" to the beginning of these folders. When I checked it looked like some folders that were obviously empty were not marked. Is it something I'm missing?? Any help would be greatly appreciated, thank you.
$CMfolder=get-childitem "Z:\folder\subfolder\subfolder2" -Recurse |
Where-Object {$_.PsIsContainer -eq $true}
$CMfolder | Where-Object {$_.GetFiles().Count -eq 0 -and
$_.GetDirectories().count -eq 0} |
where-object {$_.Name -Notlike "NA -*"} |
Rename-Item -NewName {"NA -" + $_.Name}
try this :
Get-ChildItem "c:\temp" -recurse -directory -Force | where Name -Notlike "NA -*" |
select *, #{N="HasChild";E={((Get-ChildItem $_.FullName -recurse -force -file).Count -ne 0)}} | where {! $_.HasChild}
Get-ChildItem "I:\TEMP_Dir_SSN\" | %{
if($_.name -ne "fullpath.txt" -or $_.name -ne "SSN_FILES.txt"){
remove-item $_.fullname
}
}
There are two files in the same directory that I don't want to delete. I want to delete all but two .txt files. They need to be preserved in the same directory. However, the rest is garbage and can be removed.
You can utilize Where-Object in your pipeline to accomplish what you're trying to do.
Get-ChildItem "I:\TEMP_Dir_SSN\" |
Where-Object { (($_.Name -notlike 'fullpath.txt') -and
($_.Name -notlike 'SSN_FILES.txt')) } |
Remove-Item
Just a note for more terse reading/writing, you can use the built-in alias GCI and Where
I would use the Exclude parameter to exclude the files:
Get-ChildItem "I:\TEMP_Dir_SSN" -Exclude "fullpath.txt","SSN_FILES.txt" | Remove-Item
I am trying to write a silent script that deletes files older than 14 days and removes empty folders. The part that deletes files work fine, but the part that deletes folders is popping up a confirmation window no matter what I do to suppress it. Here's my code:
$date=(get-date).AddDays(-14)
$ConfirmPreference="None"
$DebugPreference="SilentlyContinue"
$ErrorActionPreference="SilentlyContinue"
$ProgressPreference="SilentlyContinue"
$VerbosePreference="SilentlyContinue"
$WarningPreference="SilentlyContinue"
$OutputEncoding=[console]::OutputEncoding
function FullNuke ([string] $strPath) {
Get-ChildItem -Path $strPath -Recurse -Force | Where-Object {!$_.PSIsContainer -and $_.LastAccessTime -lt $date} | Remove-Item -Force
#The line below is the one that triggers the confirmation
Get-ChildItem -Path $strPath -Recurse -Force | Where-Object {$_.PSIsContainer -and #(Get-ChildItem -LiteralPath $_.FullName -Recurse -Force | Where-Object {!$_.PSIsContainer}).Length -eq 0} | Remove-Item -Force
}
Most of the answers I have found say to add -Recurse to my final Remove-Item command, but that would be the opposite of what I want. If the folder is empty, I want it removed. If it is not empty, I do not want it removed. I'm not sure why non-empty folders are even being caught in the first place.
UPDATE
After much frustration, I discovered that the second line was processing items in reverse order, thus requiring confirmation. It was also not properly identifying empty folders, which also triggered confirmation. I ended up using the following function.
function FullNuke ([string] $strPath) {
Get-ChildItem -Path $strPath -Recurse -Force | Where-Object {!$_.PSIsContainer} | Where-Object {$_.LastAccessTime -lt $date} | Remove-Item -Force
Get-ChildItem -Path $strPath -Recurse -Force | Where-Object {$_.PSIsContainer} | Where-Object {#(Get-ChildItem -LiteralPath $_.FullName -Recurse -Force).Length -eq 0} | Remove-Item -Force
}
I put it here because while it is a solution (it erases files and folders to my satisfaction), it is not an answer to my posted question.
Remove -Force from first Get-ChildItem and add -Recurse and -Confirm:$false.
This will work:
Get-ChildItem -Path $strPath -Recurse |
Where-Object {$_.PSIsContainer -and
#(Get-ChildItem -LiteralPath $_.FullName -Recurse -Force |
Where-Object {!$_.PSIsContainer}).Length -eq 0} |
Remove-Item -Force -Recurse -Confirm:$false
If you are using v3 or higher powershell client you can use the -directory and -file switches for Get-ChildItem and use this:
function FullNuke ([string] $strPath) {
Get-ChildItem -Path $strPath -Recurse -Force -File | Where-Object {$_.LastAccessTime -lt $date} | Remove-Item -Force
Get-ChildItem -Path $strPath -Recurse -Force -Directory | Where-Object {(gci $_.FullName -File -Recurse -Force).count -eq 0} | Remove-Item -Force -Recurse
}
Yes, I added -Recurse to the folder removal because with my testing no folders with any files in them were being passed to that point, and if it is a folder with nothing but empty folders in it then they all need to go anyway right?