Jump to content

Recommended Posts

Posted (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 by randle
Posted

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...

Posted

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.

Posted

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

  • Thanks 1
Posted

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.

Posted

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

Posted (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 by randle
Posted

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

  • Thanks 1
Posted

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!?

Posted
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.
  • Thanks 1
Posted (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 by Arthur
  • Thanks 2
Posted
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
Posted
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.....
Posted

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?

Posted
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)? :)

  • Thanks 1
Posted
Thanks Arthur, this looks great and love the addition of the "Disk space saved". I really appreciated the effort you went to here :D
  • 10 months later...
Posted (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 by randle

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 account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...