Delete user files - windows

I have created a script to delete the files of the users within the assigned path.
I'd like to unify the variables so I don't make it too long.
$folder = "C:\Users\$env:USERNAME\*"
$folder2 = "C:\Users\$env:USERNAME\Desktop\*"
$folder3 = "C:\Users\$env:USERNAME\Documents\*"
$folder4 = "C:\Users\$env:USERNAME\Contacts\*"
$folder5 = "C:\Users\$env:USERNAME\Downloads\*"
$folder6 = "C:\Users\$env:USERNAME\Favorites\*"
$folder7 = "C:\Users\$env:USERNAME\links\*"
$folder8 = "C:\Users\$env:USERNAME\Music\*"
$folder9 = "C:\Users\$env:USERNAME\OneDrive\*"
$folder10 = "C:\Users\$env:USERNAME\Pictures\*"
$folder11 = "C:\Users\$env:USERNAME\Searches\*"
$folder12 = "C:\Users\$env:USERNAME\Videos\*"
If (Test-Path $folder) {
Remove-Item $folder -Exclude AppData,Contacts,Desktop,Documents,Downloads,Favorites,Links,Music,OneDrive,Pictures,Searches,Videos -Force -ErrorAction SilentlyContinue
Remove-Item $folder2 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder3 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder4 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder5 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder6 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder7 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder8 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder9 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder10 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder11 -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $folder12 -Recurse -Force -ErrorAction SilentlyContinue
}
I've tried the following way and it doesn't work:
$folder = "C:\Users\$env:USERNAME\*"
$folder2 = "C:\Users\$env:USERNAME\Desktop\*"
$folder3 = "C:\Users\$env:USERNAME\Documents\*"
$folder4 = "C:\Users\$env:USERNAME\Contacts\*"
$folder5 = "C:\Users\$env:USERNAME\Downloads\*"
$folder6 = "C:\Users\$env:USERNAME\Favorites\*"
$folder7 = "C:\Users\$env:USERNAME\links\*"
$folder8 = "C:\Users\$env:USERNAME\Music\*"
$folder9 = "C:\Users\$env:USERNAME\OneDrive\*"
$folder10 = "C:\Users\$env:USERNAME\Pictures\*"
$folder11 = "C:\Users\$env:USERNAME\Searches\*"
$folder12 = "C:\Users\$env:USERNAME\Videos\*"
If (Test-Path $folder) {
Remove-Item $folder -Exclude AppData,Contacts,Desktop,Documents,Downloads,Favorites,Links,Music,OneDrive,Pictures,Searches,Videos -Force -ErrorAction SilentlyContinue
Remove-Item $folder2 + $folder3 + $folder4 + $folder5 + $folder6 + $folder7 + $folder8 + $folder9 + $folder10 + $folder11 + $folder12 -Recurse -Force -ErrorAction SilentlyContinue
}
I would also like to get a log of what has been done, for example, if files or folders were found within the paths.
Thank you so much.

The -Path parameter of Remove-Item accepts a string array as input, if you want to remove more than one item at once.
Now with the syntax $folder2 + $folder3 you are creating a concatenated string like: "C:\Users\foo\Desktop\*C:\Users\foo\Desktop\*"". That is nothing that Remove-Item can handle.
You can build a string array of paths like this:
$folder = "C:\Users\$env:USERNAME"
$foldersToRemove = #(
"C:\Users\$env:USERNAME\Desktop",
"C:\Users\$env:USERNAME\Documents",
"C:\Users\$env:USERNAME\Contacts",
"C:\Users\$env:USERNAME\Downloads",
"C:\Users\$env:USERNAME\Favorites",
"C:\Users\$env:USERNAME\links",
"C:\Users\$env:USERNAME\Music",
"C:\Users\$env:USERNAME\OneDrive",
"C:\Users\$env:USERNAME\Pictures",
"C:\Users\$env:USERNAME\Searches",
"C:\Users\$env:USERNAME\Videos")
If (Test-Path $folder) {
Remove-Item $folder -Exclude AppData, Contacts, Desktop, Documents, Downloads, Favorites, Links, Music, OneDrive, Pictures, Searches, Videos -Force -ErrorAction SilentlyContinue
Remove-Item $foldersToRemove -Recurse -Force -ErrorAction SilentlyContinue
}
About your second requirement:
The -Verbose parameter will make Remove-Item tell you, which folders are removed. If you need your log in a file, you can redirect the verbose stream like this:
Remove-Item $foldersToRemove -Recurse -Force -ErrorAction SilentlyContinue -Verbose 4> .\deletedFolders.log

Related

Getting root folder name with PS

I am trying to create a PowerShell script to fetch the root folder's name where in their subdirectories files with error names are present with today's date. Below is the sample code I have tried so far to pick the folder names.
Root Log folder - C:\Errorlogs, contains many other application log level folders.
$targetDir="C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*"|
where {([datetime]::now.Date -eq $_.lastwritetime.Date)} |
select FullName
I have tried the above code; however, it's giving me the whole path as result, whereas I only need the folder name.
Result - C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\04\Error.txt
Required - AsyncCreateUsersAPIProcessor
Use string LastIndexOf and SubString
$rootPath = "C:\Temp\Errorlogs"
$date = [DateTime]::Now.ToString("yyyyMM\\\\dd")
$pattern = '\\(?<folder>\w+)\\' + $date + '\\Error.*$'
$files = Get-ChildItem -Path $rootPath -Recurse | Select-Object -Property Fullname | Where-Object {$_.Fullname -Match $pattern}
foreach($file in $files)
{
$file.Fullname -match $pattern
Write-Host "folder = " $Matches.folder
}
Looks like you can do it just with splitting the path using \ as delimiter then picking the 3rd token (2nd index of an array):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.FullName.Split('\')[2] }}
Another option if you want 2 levels up in the folder hierarchy is to query the .Directory property of the file then the .Parent property of the parent folder (2 times or as many times as needed):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.Directory.Parent.Parent.Name }}
As long as the subfolders inside the folder you are after all have numeric-only names, you can loop backwards to get at the first non-numeric foldername and output that.
$targetDir = "C:\Errorlogs"
Get-ChildItem -Path $targetDir -File -Filter "*Error*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } | ForEach-Object {
$parentDir = $_.Directory
while ($parentDir.Name -match '^\d+$') { $parentDir = $parentDir.Parent }
$parentDir.Name
}
That way, even a path C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\02\04\1234\567\Error.txt would produce folder name AsyncCreateUsersAPIProcessor

How to keep firefox bookmarks with powershell?

like in What is the difference between opening application by cmd/ps or by click? already discussed, I have the problem, that firefox does not use my bookmarks, that I copied with powershell, as long as I open/close firefox within a script.
The only chance I have is: open/close firefox manually and then overwrite bookmarks/passwords with powershell.
Also I created the profile with arguments, but as soon as firefox will be opened, firefox is creating a new profile on its own. Obviously it makes a difference, whether I open firefox by click or ps/cmd.
Does anybody has an idea, how to tell firefox which profile it shall use when the user opens firefox?
Here my code:
# Full path of the file
$appdata = $env:APPDATA
$folder = "$appdata\Custom"
$checkfile = "$folder\firstRunRestore"
#If the file does not exist, create it and execute statement.
if (-not(Test-Path -Path $checkfile -PathType Leaf)) {
try {
$null = New-Item -ItemType File -Path $checkfile -Force -ErrorAction Stop
#Create Firefox profile
$p = New-Object System.Diagnostics.Process
$p.StartInfo.UseShellExecute = $true;
$p.StartInfo.WorkingDirectory = "C:\Program Files\Mozilla Firefox";
$p.StartInfo.Filename = "firefox.exe";
$p.StartInfo.Arguments = "-CreateProfile $env:USERNAME";
$null = $p.Start()
Start-Sleep -s 10
Stop-Process -Name "Firefox"
# Wait to close all processes
Start-Sleep -s 7
# Restore files to profile
$firefox = "$env:APPDATA\Mozilla\Firefox\Profiles"
$curProfile = Get-ChildItem -Path $firefox | Sort-Object LastAccessTime -Descending | Select-Object -First 1
$curPath = "$firefox\$curProfile"
$source = "X:\Desktop\FF-Profile"
$keydb = "key4.db"
$logins = "logins.json"
$places = "places.sqlite"
$favicons = "favicons.sqlite"
Copy-Item -Path "$source\$keydb" -Destination "$curPath" -Force
Copy-Item -Path "$source\$logins" -Destination "$curPath" -Force
Copy-Item -Path "$source\$places" -Destination "$curPath" -Force
Copy-Item -Path "$source\$favicons" -Destination "$curPath" -Force
Remove-Item $source -Force -Recurse
}
catch {
throw $_.Exception.Message
}
}

Why is my Move-Item command filtering not detected?

My command to move all rar files
Move-Item -Path * -Filter *.rar -Destination .\Target
I changed a little bit
Move-Item -Path * -Filter .\*.rar -Destination .\NewTarget
Same issue again,rar is not filtered.
Everything is moved to Target(all files). Why?
I think this should to the work :-)
It is better to filter them before with Get-ChildItem and store them at some variable. And then when you know that you have exact files just doing it with ForEach or ForEach-Object
$Source = "C:\Users\Puzo\Desktop\FolderA"
$Destination = "C:\Users\Puzo\Desktop\FolderB"
$FilesToMove = Get-ChildItem -Path $Source -Filter "*.rar" -Recurse
$i = 1
ForEach ($File in $FilesToMove)
{
Move-Item -Path $File.FullName -Destination ("$Destination\" + $File.Name)
Write-Host ('File ' + $File.Name + 'was moved.') -ForegroundColor Yellow
$i++
}
Write-Host "$i files was moved!" -ForegroundColor Green

how to remove directories structures not accessed since a specific date?

how to remove directories structures not accessed since a specific date ?
it might look like something :
Get-ChildItem -Path $path -Recurse -Force -filter IDENTIFY_DIRECTRORY | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | IDENTIFYTHELASTACCCESSTIME | Remove-Item -Force
IDENTIFY_DIRECTORY : I guess it is : -Directory parameter to Get-ChildItem command (select directories only not files)
IDENTIFYTHELASTACCCESSTIME : here I mean check if directory or sub-path/file has been accessed/read since a date I would set from a variable
Final goal of that is to purge useless files from a fileserver to free a maximum of space.
I already did :
Get-ChildItem -Path $path -Recurse -Force -filter *.log | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
maybe workaround
Get-ChildItem -Path "F:\" $_.LastAcessTime -Recurse -Directory -Force -<somemorecommandlineparameters> ......

Powershell script for

I have Windows Server 2016 Datacenter (64 bit) as a File Server (contains several Shared folder & subfolders).
I want to make a list OR export user Folder Structure along with permissions ( Read, Modify, Full .. etc..)
I tried with below PS script but I am getting an error message with I have mentioned after the script.
Powershell
$FolderPath = dir -Directory -Path "E:\Project Folders\#Folder_Name" -Recurse -Force
$Report = #()
Foreach ($Folder in $FolderPath) {
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]#{'FolderName'=$Folder.FullName;'AD Group or User'=$Access.IdentityReference;'Permissions'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
$Report | Export-Csv -path "C:\Folder Permissions\Folder Name.csv"
Error:
dir : Access to the path 'E:\Project Folders**Folder Path**\New folder' is denied. At C:\Users\Administrator\Documents\PS Script**File Name**.ps1:1 char:15 + ... olderPath = dir -Directory -Path "E:\Project Folders**Folder Name**" -Re ...+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (E:\Project Fold...ngar\New folder:String) [Get-Child Item], UnauthorizedAccessException + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
Please help me out!
Thanks in Advance
As noted by the other comments.
This is not a PowerShell error/issue, it is a permissions one. The same thing can/will happen if you say you did this use case on the Windows folder tree.
Since you know this will happen, either fix the permissions on the tree you are working on or do this.
Get-ChildItem -Directory -Path 'C:\Windows\System32' -Recurse -ErrorAction SilentlyContinue
or if you want to just stop when a path fails.
# Treat non-terminating erros as terminating
$RootFolderUnc = 'C:\Windows\System32'
Try {Get-ChildItem -Directory -Path $RootFolderUnc -Recurse -ErrorAction Stop}
Catch [System.UnauthorizedAccessException]
{
Write-Warning -Message "$env:USERNAME. You do not have permissions to view this path."
$_.Exception.Message
}

Resources