So my boss needs me to create a script that deletes everything in a directory with the exception of the folders with the name "incoming" and "outgoing," while still deleting all files and directories within those folders. These two folders are also stored in random company name folders so I cant specify each one as the list will keep growing.
How can I delete all the incoming and outgoing folder contents without deleting the folder that those folders are stored in?
Here is the code I have so far:
Get-ChildItem -Path ("C:\Users\testuser\Desktop\Test") -Exclude "Incoming","Outgoing" | foreach ($_) {
"CLEANING :" + $_.FullName
Remove-Item $_.FullName -Force -Recurse
"CLEANED... :" + $_.FullName
}
Is this the right approach? is there a switch or something that I should be adding to this command to add extra options? This script will be run daily via a Windows task I'm going to setup. Maybe there's a way to specify how deep the deletion script goes?
Hopefully this is what you need. This should delete files and folders that are in under the folders "Incoming" and "Outgoing."
$folders = Get-ChildItem -Path "C:\Users\mkrouse\Desktop\Test" -Recurse -Directory | Where-Object {($_.basename -contains "Incoming") -or ($_.BaseName -contains "Outgoing")}
foreach($folder in $folders){
$items = Get-ChildItem -Path $folder.FullName -Recurse
foreach($file in $items) {
Remove-Item -Path $file.FullName -Recurse -Force -WhatIf
}
}
Related
so trying to find a way to combine a couple of things the Stack Overflow crowd has helped me do in the past. So I know how to find folders with a specific name and move them where I want them to go:
$source_regex = [regex]::escape($sourceDir)
(gci $sourceDir -recurse | where {-not ($_.psiscontainer)} | select -expand fullname) -match "\\$search\\" |
foreach {
$file_dest = ($_ | split-path -parent) -replace $source_regex,$targetDir
if (-not (test-path $file_dest)){mkdir $file_dest}
move-item $_ -Destination $file_dest -force -verbose
}
And I also know how to find and delete files of a specific file extension within a preset directory:
Get-ChildItem $source -Include $searchfile -Recurse -Force | foreach{ "Removing file $($_.FullName)"; Remove-Item -force -recurse $_}
What I'm trying to do now is combine the two. Basically, I'm looking for a way to tell Powershell:
"Look for all folders named 'Draft Materials.' When you find a folder with that name, get its full path ($source), then run a command to delete files of a given file extension ($searchfile) from that folder."
What I'm trying to do is create a script I can use to clean up an archive drive when and if space starts to get tight. The idea is that as I develop things, a lot of times I go through a ton of incremental non-final drafts (hence folder name "Draft Materials"), and I want to get rid of the exported products (the PDFs, the BMPs, the AVIs, the MOVs, atc.) and just leave the master files that created them (the INDDs, the PRPROJs, the AEPs, etc.) so I can reconstruct them down the line if I ever need to. I can tell the script what drive and folder to search (and I'd assign that to a variable since the backup location may change and I'd like to just change it once), but I need help with the rest.
I'm stuck because I'm not quite sure how to combine the two pieces of code that I have to get Powershell to do this.
If what you want is to
"Look for all folders named 'Draft Materials.' When you find a folder with that name, get its full path ($source), then run a command to delete files of a given file extension ($searchfile) from that folder."
then you could do something like:
$rootPath = 'X:\Path\To\Start\Searching\From' # the starting point for the search
$searchFolder = 'Draft Materials' # the folder name to search for
$deleteThese = '*.PDF', '*.BMP', '*.AVI', '*.MOV' # an array of file patterns to delete
# get a list of all folders called 'Draft Materials'
Get-ChildItem -Path $rootPath -Directory -Filter $searchFolder -Recurse | ForEach-Object {
# inside each of these folders, get the files you want to delete and remove them
Get-ChildItem -Path $_.FullName -File -Recurse -Include $deleteThese |
Remove-Item -WhatIf
}
Or use Get-ChildItem only once, having it search for files. Then test if their fullnames contain the folder called 'Draft Materials'
$rootPath = 'X:\Path\To\Start\Searching\From'
$searchFolder = 'Draft Materials'
$deleteThese = '*.PDF', '*.BMP', '*.AVI', '*.MOV'
# get a list of all files with extensions from the $deleteThese array
Get-ChildItem -Path $rootPath -File -Recurse -Include $deleteThese |
# if in their full path names the folder 'Draft Materials' is present, delete them
Where-Object { $_.FullName -match "\\$searchFolder\\" } |
Remove-Item -WhatIf
In both cases I have added safety switch -WhatIf so when you run this, nothing gets deleted and in the console is written what would happen.
If that info shows the correct files are being removed, take off (or comment out) -Whatif and run the code again.
I have batch changed multiple files that all start with a prefix of a folder where I need them in.
The files are located on another location, like a folder on the desktop.
For example:
101AA0001.dat
101AA0002.dat
102AA0001.dat
102AA0002.dat
The destination folder will for example be:
C:\destfolder\101\ or C:\destfolder\102\
Files starting with 101 need to go in the 101 folder and the files starting with 102 go to folder 102.
I can find some scripts that creates the folder based on the filename. But in this situation the folders already exist. I also know for sure the files don't exist, so I don't have to overwrite files or something.
I guess it is easy for the people that know PowerShell very well, but I don't know how to do this. Can someone please help me? This can save me a lot of time.
I have tried to move the files with the following rule:
Move-Item -Path C:\Users\Username\Desktop\test*.dat -Destination C:\Users\Username\Desktop\test2\ -include "*.dat"
But it copies the whole folder except for the files.
You can do that quite easily with code like below:
$sourceFolder = Join-Path -Path $env:USERPROFILE -ChildPath 'Desktop'
$destination = 'C:\destfolder'
Get-ChildItem -Path $sourceFolder -File -Filter '*.dat' | ForEach-Object {
$targetFolder = Join-Path -Path $destination -ChildPath $_.Name.Substring(0, 3)
# if the target folder does not exist yet, create it
if (!(Test-Path -Path $targetFolder -PathType Container)) {
$null = New-Item -Path $targetFolder -ItemType Directory
}
$_ | Move-Item -Destination $targetFolder -WhatIf
}
The -WhatIf switch shows what would happen in the console without actually performing the move. If you are satisfied with what is output, remove that switch.
This will take all files that end in ".dat" from the $Source folder into a subfolder inside the $DestinationRoot named for the first three characters of the ".dat" file.
$Source = "C:\Users\Username\Desktop"
$DestinationRoot = "C:\Users\Username\Desktop\test2"
$Filelist = Get-ChildItem -Path $Source -Filter "*.dat" -File
foreach ($File in $Filelist){ $DestinationFolder = $File.Name.Substring(0,3)
$FinalPath = "$DestinationRoot\$DestinationFolder"
Move-Item -Path $File.Fullname -Destination $FinalPath -Whatif }
Remove the -Whatif when you're ready to run it for real.
This doesn't handle folder creation and should error out if the file already exists in the target location so it won't accidentally overwrite anything.
I need to write a script that deletes folders with last write time ~7 Days. But keep 2 "special" folder with the content in it.
Here's my script so far:
$source = "D:\TestOrdner"
$time = (Get-Date)#.AddDays(-7)
Start-Transcript "C:\log_files\log.txt"
gci $source -Recurse | ?{$_.LastWriteTime -lt $time} | del -Force -Verbose
Stop-Transcript
My only problem is how to EXCLUDE the folders with content?
My folder to keep: D:\TestOrdner\Test.
Be careful when deleting user profile folders, so keep the -WhatIf switch until you are absolutely sure the below will not delete folders that should not be deleted.
It might be a good idea to Move these folders instead of deleting them?
Since this concerns a user profile folder where every user has his/her own folder directly under the root folder, there is no need for the -Recurse switch on Get-ChildItem
Anyhow, this should do it:
$source = "D:\TestOrdner"
$time = (Get-Date).AddDays(-7)
Start-Transcript "C:\log_files\log.txt"
Get-ChildItem $source -Directory -Exclude 'Administrator','Default','Public' |
Where-Object {$_.LastWriteTime -lt $time} |
Remove-Item -Recurse -Force -confirm:$false -WhatIf
Stop-Transcript
I'm trying to use PowerShell to copy a folder with sub-folders from our users to a small backup. These folders contain a folder called "windows" I don't want to copy.
I have tried "exclude" but can't seem to get it to work.
This is the script so far:
Copy-Item "E:\Curos folder" -Exclude 'Windows' -Destination "E:\Curos folder backup" -Recurse -Verbose
I have read other posts but don't quiet understand how it works
It's my first time working with PowerShell
You are complete right.
Actually the script it's simpler than the one I have wrote before.
Here we go:
$source = "C:\Users\gaston.gonzalez\Documents\02_Scripts"
$destination = "D:\To Delete"
$exclude = "Windows"
$folders = Get-ChildItem -Path $source | Where {($_.PSIsContainer) -and ($exclude -notcontains $_.Name)}
foreach ($f in $folders){
Write-Host "This folders will be copied: $f"
Copy-Item -Path $source\$f -Destination $destination\$f -Recurse -Force
}
I'd use something like this:
Get-ChildItem $root -Directory -Recurse | % {$_.name -ne 'Windows'} | foreach {Copy-Item "$($_.FullName)" -Destination $dest -Recurse}
I haven't tested it but it's the skeleton of something you should be able to make work, although I don't find the point of using recurse on both, Get-ChildItem and Copy-Item my advice is to use it on Get-ChildItem.
I am trying delete all files within a folder but there is 1 folder called pictures which I would like to keep but don't know how to do that. I am using the following script , it deletes everything in a folder
if ($message -eq 'y')
{
get-childitem "C:\test" -recurse | % {
remove-item $_.FullName -recurse
}
}
One solution is to use something like:
Get-ChildItem -Path "c:\test" -Recurse | Where-Object { $_.FullName -cnotmatch "\\Pictures($|\\)" -and (Get-ChildItem $_.FullName -Include "Pictures" -Recurse).Length -eq 0 } | Remove-Item -Recurse -ErrorAction SilentlyContinue;
I suspect there must be a way more elegant way to do this. Here's what this does: it enumerates all files in the C:\test folder recursively (Get-ChildItem), then it removes all items from the result list using Where-Object where the path contains the directory to be excluded (specified using regex syntax) or when the item in question has child items that contains the file or directory to be excluded. The resulting list is fed to Remove-Item for removal. The -ErrorAction SilentlyContinue switch is applied to prevent errors being logged with recursive removal.
Get-ChildItem $PSScriptRoot -Force| Where-Object {$_.Name -ne "Pictures"} | Remove-Item -Recurse
I just tried this, and it worked for me. If you want to change what is deleted just change the "Pictures". This uses $PSScriptRoot for the path, which is the execution path of the Powershell script. You can rename that to be the path of where you want to delete.