randle Posted June 11, 2014 Posted June 11, 2014 (edited) Hi, I have a PS script I'm working on and need a little advice on excluding some folders. I have the following code:Remove-Item -recurse -path "$studentPath\My Settings\Application Data\*" -Exclude RM,Macromedia,Sun,"Internet*" -force The "Internet*" exclusion is to actually exclude the folder "Internet Explorer" inside the Microsoft folder however, this folder is retained but the content is still deleted. I was under the impression that this would exclude the folder and contents but obviously isn't the case. Any advice? Edited June 11, 2014 by randle
randle Posted June 11, 2014 Author Posted June 11, 2014 The recurse parameter appears to delete all content regardless of excluding the folders. Only the folders remain. Taking out the -recurse parameter does keep the contents of the first three folders but not the contents of the child folder "Internet Explorer" for some reason. The problem is that without this parameter it prompts for deletion...
Arthur Posted June 11, 2014 Posted June 11, 2014 Try this... $Exclusions = "RM","Macromedia","Sun","Internet*" Get-ChildItem -Path "$studentPath\My Settings\Application Data\" -Recurse -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force -WhatIf Notes. Do not put an asterisk at the end of the path. Remove the '-WhatIf' parameter at the end to actually delete files and folders.
Arthur Posted June 11, 2014 Posted June 11, 2014 Assuming you have PowerShell 3.0 (or greater) installed, you can also make the script run faster by adding the 'Directory' parameter to Get-ChildItem. $Exclusions = "RM","Macromedia","Sun","Internet*" Get-ChildItem -Path "$studentPath\My Settings\Application Data\" -Directory -Recurse -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force -WhatIf 1
randle Posted June 12, 2014 Author Posted June 12, 2014 Hi Arthur, Thanks for the help however, have the following outcome on a test area - The Macromedia and Sun folders are now empty. These had folders below them prior to running the script. I can't see why these are touched when the parent folders are set to be excluded!!? - The RM folder has retained a single file that existed so looks like files are now no longer being removed - The Microsoft folder which contained the Internet Explorer folder has been removed so the "Internet*" exclusion has been ignored by the looks of it.
Arthur Posted June 12, 2014 Posted June 12, 2014 What happens if you remove the Recurse parameter from Remove-Item? 1
old_n07 Posted June 12, 2014 Posted June 12, 2014 If you remove the recurse on the GCI part of the code it will only retrieve the top level folders excluding the items in exclusion list, then use recurse on the remove-item to delete the top level folders and their contents $Exclusions = "RM","Macromedia","Sun","Internet*" Get-ChildItem -Path "$studentPath\My Settings\Application Data\" -Directory -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force HTH Neil
randle Posted June 12, 2014 Author Posted June 12, 2014 (edited) Now we're cooking. I've removed the recurse parameter from the gci section and now leaves the content and files o the excluded folders behind however, still isn't retaining the Internet Explorer folder below the Microsoft folder! Just seen your update Neil and confirms the above. Without the recurse parameter the IE folder is not kept. Is there any way around this? Edited June 12, 2014 by randle
old_n07 Posted June 12, 2014 Posted June 12, 2014 Not sure on how to do it easily in one line but this will do it in two $Exclusions = "RM","Macromedia","Sun","Microsoft" Get-ChildItem -Path "$studentPath\My Settings\Application Data\" -Directory -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force Get-ChildItem -Path "$studentPath\My Settings\Application Data\Microsoft" -Directory -Exclude "Internet*" | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force Exclude the Microsoft directory as a whole from the first delete then perform the same function just on the MS folder excluding IE Neil 1
randle Posted June 12, 2014 Author Posted June 12, 2014 Ah yes of course. I think that'll work fine for what I want. Thanks for that. Just out of interest, why does the gci command need to be piped through to "Select -ExpandProperty FullName | Sort Length -Descending". I can't see what this adds to help the process!?
old_n07 Posted June 12, 2014 Posted June 12, 2014 The "Select -ExpandProperty FullName " returns the full path and name of the folder and the sort just orders the output, but thy can both be omitted from the code and it still works. 1
Arthur Posted June 12, 2014 Posted June 12, 2014 (edited) Just out of interest, why does the gci command need to be piped through to "Select -ExpandProperty FullName | Sort Length -Descending". I can't see what this adds to help the process!? Because this... The -recurse switch does not work properly on Remove-Item (it will try to delete folders before all the child items in the folder have been deleted). Sorting the fullnames in descending order by length ensures that no folder is deleted before all the child items in the folder have been deleted. (Source) Edited June 12, 2014 by Arthur 2
randle Posted June 12, 2014 Author Posted June 12, 2014 Ah yes I remember seeing that now but was before using the gci Cmdlet so didn't pay too much attention to it. Thanks again guys
randle Posted June 12, 2014 Author Posted June 12, 2014 Just one other question while I'm here if you wouldn't mind. I would think this an easy addition but am struggling to see how I can output all actions of the script to a file. I'm searching for a solution at the moment but from what I can see doesn't look to be as straight forward as I was hoping.....
randle Posted June 12, 2014 Author Posted June 12, 2014 I've managed to have a bit of luck using the tee Cmdlet and all is now outputting to a file except one command. It's probably easier to post the script# Server to run command on $serverName = Read-Host "Server Name" | tee "\\svroffice01\d$\Temp\Test\test.txt" -Append # Display directory size #Get-Size "\\$serverName\d$\Temp\Test\RMStudentWork" "Directory size pre cleanup: {0:N2}" -f ((Get-ChildItem -path "\\$serverName\d$\Temp\Test\RMStudentWork" -recurse | Measure-Object -property length -sum ).sum /1MB) + " MB" | tee "\\svroffice01\d$\Temp\Test\test.txt" -Append # Get a list of Intake years $intakeFolderPaths = gci "\\$serverName\d$\Temp\Test\RMStudentWork" -exclude *.ini # Cyle through users in each Intake year Foreach ($intakeYear in $IntakeFolderPaths) { # Get a list of user names $studentFolderPath = gci $intakeYear -exclude *.ini # Assign path variable to each student in $studentFolderPath foreach ($studentPath in $studentFolderPath) { # Remove all folders and files except exclusions within the My Settings folder $Exclusions = "RM","Macromedia","Sun","Microsoft","Adobe" Get-ChildItem -Path "$studentPath\My Settings\Application Data\" -Directory -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force Get-ChildItem -Path "$studentPath\My Settings\Application Data\Adobe" -Directory -Exclude "Flash*" | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force Get-ChildItem -Path "$studentPath\My Settings\Application Data\Microsoft" -Directory -Exclude "Internet*" | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force # Confirm deletion to console, can be removed Write-Host "$studentPath My Settings cleaned up" | tee "\\svroffice01\d$\Temp\Test\test.txt" -Append } } # Display directory size #Get-Size "\\$serverName\d$\Temp\Test\RMStudentWork" "Directory size post cleanup: {0:N2}" -f ((Get-ChildItem -path "\\$serverName\d$\Temp\Test\RMStudentWork" -recurse | Measure-Object -property length -sum ).sum /1MB) + " MB" | tee "\\svroffice01\d$\Temp\Test\test.txt" -Append Pause The part that isn't outputting is the "Confirm deletion to console...." section. Am I adding this Cmdlet in the wrong place maybe?
Arthur Posted June 13, 2014 Posted June 13, 2014 So close.....Anyone? This might help? function Tidy-AppData { [CmdletBinding()] param ( [Parameter(Mandatory=$true, Position=0, HelpMessage=’The server containing the user areas to cleanup’)] [ValidateNotNullOrEmpty()] [string] $ServerName ) [Double]$PreCleanup = '{0:0.00}' -f ((Get-ChildItem -Path "FileSystem::\\$ServerName\X$\RMStudentWork" -Recurse | Measure-Object -Property Length -Sum).Sum/1MB) Write-Verbose -Message "Directory size before cleanup: $PreCleanup MB" # Insert code to delete stuff here [Double]$PostCleanup = '{0:0.00}' -f ((Get-ChildItem -Path "FileSystem::\\$ServerName\X$\RMStudentWork" -Recurse | Measure-Object -Property Length -Sum).Sum/1MB) Write-Verbose -Message "Directory size after cleanup: $PostCleanup MB" $Freed = $PreCleanup - $PostCleanup Write-Verbose -Message "Disk space saved: $Freed MB" } # Example Tidy-AppData -ServerName DC1 -Verbose 4>&1 | Tee-Object -FilePath $PSScriptRoot\AppDataLog.txt I can explain how it works in more detail later (if required)? 1
randle Posted June 16, 2014 Author Posted June 16, 2014 Thanks Arthur, this looks great and love the addition of the "Disk space saved". I really appreciated the effort you went to here
randle Posted May 10, 2015 Author Posted May 10, 2015 (edited) Just resurrecting this thread as have improved this script by adding an option menu to allow you to select what type of user you want the script to run against. Saves having to create multiple scripts etc. The script appears to work fine however, the Measure-Object cmdlet after the tidy up doesn't appear to be working and just returns 0 MB when in fact this share does have a value. I can't see why this works fine before the clean-up but not after! Any ideas? function Tidy-AppData { [CmdletBinding()] param ( [Parameter(Mandatory=$true, Position=0, HelpMessage=’The server containing the user areas to cleanup’)] [ValidateNotNullOrEmpty()] [string] $ServerName ) Write-Verbose -Message "Script run time: $(Get-Date -format 'G')" Write-Verbose -Message "Executed on: $ServerName" [Double]$PreCleanup = '{0:0.00}' -f ((Get-ChildItem -Path "FileSystem::\\$ServerName\$UserType" -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum/1MB) Write-Verbose -Message "Directory size before cleanup: $PreCleanup MB" # Get a list of Intake years $UserTypeFolderPaths = gci "[url="file://\\$ServerName\$UserType"]\\$ServerName\$UserType[/url]" -include Intake*,Bin*,Exam*,Controlled*,LSA*,Permanent,Temporary,Training,Admin,Curriculum*,Guests # Cyle through users in each Intake year Foreach ($UserType in $UserTypeFolderPaths) { # Get a list of user names $UserFolderPath = gci $UserType -exclude *.ini # Assign path variable to each student in $studentFolderPath foreach ($UserPath in $UserFolderPath) { # Remove all folders and files except exclusions within the My Settings folder $Exclusions = "RM","Macromedia","Sun","Microsoft","Adobe" Get-ChildItem -Path "$UserPath\My Settings\Application Data" -Directory -Exclude $Exclusions | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue Get-ChildItem -Path "$UserPath\My Settings\Application Data\Adobe" -Directory -Exclude "Flash*" | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue Get-ChildItem -Path "$UserPath\My Settings\Application Data\Microsoft" -Directory -Exclude "Internet*","Outlook","CLR*","Signatures","A2C*" | Select -ExpandProperty FullName | Sort Length -Descending | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue # Confirm deletion to console, can be removed Write-Verbose -Message "$UserPath My Settings cleaned up" } } [Double]$PostCleanup = '{0:0.00}' -f ((Get-ChildItem -Path "FileSystem::\\$ServerName\$UserType" -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum/1MB) Write-Verbose -Message "Directory size after cleanup: $PostCleanup MB" $Freed = $PreCleanup - $PostCleanup Write-Verbose -Message "Disk space saved: $Freed MB" Write-Verbose -Message "Script end time: $(Get-Date -format 'G')" } # Server to run command on $sw = [Diagnostics.Stopwatch]::StartNew() $ServerName = (Read-Host "Server Name") While (!(Test-Path [url="file://\\$ServerName\c$"]\\$ServerName\c$[/url])) { $ServerName = (Read-Host "Server could not be contacted. Check name and retry") } do { [int]$xMenuChoiceA = 0 while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 4 ){ Write-host "`n1. Student" Write-host "2. Teaching Staff" Write-host "3. Non-Teaching Staff" Write-host "4. Exit" [int]$xMenuChoiceA = read-host "`nWhat type of user would you like to clean? Select 1 to 4..." } Switch( $xMenuChoiceA ){ 1{$UserType = "RMStudentWork"} 2{$UserType = "RMTeacherWork"} 3{$UserType = "RMNonTeacherWork"} 4{Exit} default{Exit} } } until (Test-path -path "[url="file://\\$ServerName\$UserType"]\\$ServerName\$UserType[/url]") Tidy-AppData -ServerName $ServerName -Verbose 4>&1 | Tee-Object -FilePath [url="file://\\ServerName\ITDepartment$\Logs\$ServerName-$UserType-AppDataLog-$(Get-Date"]\\ServerName\ITDepartment$\Logs\$ServerName-$UserType-AppDataLog-$(Get-Date[/url] -f yyyy-MM-dd).txt $sw.Stop() $sw.Elapsed explorer [url="file://\\ServerName\ITDepartment$\Logs"]\\ServerName\ITDepartment$\Logs\[/url] Pause[/Code] Edited May 10, 2015 by randle
randle Posted May 12, 2015 Author Posted May 12, 2015 Ahh ignore the last post. I'm being a numpty and doubling up on variables.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now