PowerShell - Double loop possible? - powershell

I want to compress a directory in a specific place.
The source path is : \\$Computers\Users\$Names
I want than for each computers a copy of each users directory in the sources path of each computers
I tried to use a foreach loop like :
$Computers = Get-ADComputer -Filter "Name -like 'PC*'" | Select-Object -ExpandProperty Name
$Names = Get-aduser -filter * | Select-Object -ExpandProperty givenname
Foreach($Computer in $Computers)
{
Compress-Archive -Path \\$Computer\Users\* -DestinationPath C:\Saves\\$Computer\Test.zip -Force
}
This actually work, but I don't know how can I add a second loop inside the loop.
If anyone can just explain me the function or just some advises please for trying to do that.
Thank you for your time.

You're approaching the problem with the wrong logic, you do need an inner loop, however, instead of attempting to compress a user profile that you don't know for sure is there you can instead query the remote computer's Users folder to see which ones are there and compress only those ones:
$Computers = (Get-ADComputer -Filter "Name -like 'PC*'").Name
# Add the profiles you want to exclude here:
$toExclude = 'Administrator', 'Public'
$params = #{
Force = $true
CompressionLevel = 'Optimal'
}
foreach($Computer in $Computers)
{
$source = "\\$Computer\Users"
Get-ChildItem $source -Exclude $toExclude -Directory | ForEach-Object {
$params.LiteralPath = $_.FullName
# Name of the zipped file would be "ComputerExample - UserExample.zip"
$params.DestinationPath = "C:\Saves\$computer - {0}.zip" -f $_.Name
Compress-Archive #params
}
}

Related

Powershell script to create folder for groups with extensionAttribute1 set

Hi I want to write a powershell scrip that creates a folder for groups in a specific OU where I have set the extensionAttribute1.
Get-ADGroup -filter * -SearchBase "OU=Groups,OU=Test,DC=test,DC=Domain,DC=en" -properties * | where {$_.extensionAttribute1}| select-object samaccountname, extensionAttribute1
so I get the list of groups with extensionAttribute1 and with
Get-ChildItem D:\Test
I get the list of already created folders.
What is the best way to compare these two lists and create one for the groups for which no folder is created yet?
Given you're scenario, you don't have to use Get-ChildItem if you just want to see if the folder already exists. Then, you would only need Test-Path and use a loop to test for each folder.
Get-ADGroup -filter * -SearchBase "OU=Groups,OU=Test,DC=test,DC=Domain,DC=en" -properties "extensionAttribute1" |
Where-Object -FilterScript { $_.extensionAttribute1 -eq "Folder" } |
ForEach-Object `
-Begin { $path = "D:\Test\" } `
-Process {
if (-not (Test-Path -LiteralPath ($path + $_.Name))) {
New-Item -Path $path -Name $_.Name -ItemType "Directory" | Out-Null
}
}

Powershell find multiple files from multiple remote computers, from all drives

Needed to make a script that finds a list of files from a list of multiple computers. The script below works fine for that.
Now would need to add a functionality so that script goes thru ALL drives per computer, not just C$. Problem is I don't know which computers have which drives..
The current script:
$computers = Get-Content .\computers.txt
$filenames = Get-Content .\filenamelist.txt
foreach ($computer in $computers) {
foreach ($filename in $filenames) {
Get-ChildItem -Recurse -Force \\$computer\c$ -ErrorAction SilentlyContinue |
Where-Object { ($_.PSIsContainer -eq $false) -and ( $_.Name -eq "$filename") } |
Select-Object Name, Directory |
Export-Csv .\FoundFiles.csv -nti -append
}
}
So I should somehow implement command line:
$Drives = Get-PSDrive -PSProvider 'FileSystem'
So that it gets run on each computer and the Get-ChildItem line run based on the result, for each existing drive on each remote computer.
Any ideas please?

How can I read multiple computer descriptions?

I want to create a script which reads all the computernames from a CSV file. And from all of these, I want the description. Also it should be exported in a single CSV.
This is what I tried but...
$path = Split-Path -Parent $MyInvocation.MyCommand.Definition
$path_import_csv = $path + "\" + "Computernamen.csv"
$path_export_csv = $path + "\" + "Alessio.csv"
$computernames = Import-Csv $path_import_csv
foreach ($computername in $computernames) {
Get-ADComputer -SearchBase "OU=1,OU=2,OU=3,DC=my,DC=domain" -Properties * |
Select -Expand description |
Export-Csv -Path $path_export_csv -Append -Delimiter ";" -NoTypeInformation -Force
}
From your comment I gather that file Computernamen.csv is not a CSV file at all, but just a text file with computer names each on a separate line.
In that case, you do not use Import-Csv, but Get-Content to retrieve an array of computer names.
Also (others already made that clear) you are not using the $computername variable in the foreach loop at all AND by adding the -ExpandProperty switch to the Select-Object cmdlet, you are not receiving an object with property Description, but just the description as string .
For outputting a CSV with Export-Csv, you need to have a (series of) objects.
Also, I would recommend using the Join-Path cmdlet for creating file paths instead of contatenating string with + so you don't have to worry about possible missing backslashes.
Instead of $MyInvocation.MyCommand.Definition you can also use the $PSScriptRoot variable to get the current script path.
In Windows PowerShell 2.0, this variable is valid only in script modules (.psm1).
Beginning in Windows PowerShell 3.0, it is valid in all scripts.
$path = Split-Path -Parent $MyInvocation.MyCommand.Definition # or use $PSScriptRoot
$path_import_csv = Join-Path -Path $path -ChildPath 'Computernamen.csv'
$path_export_csv = Join-Path -Path $path -ChildPath 'Alessio.csv'
$computernames = Get-Content $path_import_csv
$searchBase = 'OU=1,OU=2,OU=3,DC=my,DC=domain'
$result = foreach ($computername in $computernames) {
# it is bad practice to use -Properties * if all you need is a small set of properties
$computer = Get-ADComputer -Filter "Name -eq '$computername'" -SearchBase $searchBase -Properties Name, Description -ErrorAction SilentlyContinue
# did we find a computer by that name?
if ($computer) {
# output an object with the two selected properties to get collected in the $result variable
$computer | Select-Object Name, Description
}
else {
Write-Host "A computer with name '$computername' does not exist."
}
}
# output the result on console
$result | Format-Table -AutoSize
# save the result as proper CSV file
$result | Export-Csv -Path $path_export_csv -Delimiter ';' -NoTypeInformation -Force

How to get folder name thats different on all user profiles

I like to know how to get 5J91Q4CX.C10 to use in a variable.
C:\Users\user\AppData\Local\Apps\2.0\5J91Q4CX.C10
On all user profiles this folder has a different name.
It is always 8 numbers and digits then a . and then 3 digits or numbers.
I need to use this for a powershell script.
Any idea how I can make a variable for this foldername?
Thanks
I'd do something like this:
#Loop through all user profile folders using something like this:
$userFolders = Get-ChildItem -Path "C:\Users\" -Directory -Force -ErrorAction SilentlyContinue |
Where-Object { #('All Users','Default User', 'Public', 'Default') -notcontains $_.Name } |
Select-Object -ExpandProperty Name
# next loop through these folders to find the foldername that can be different for each user
foreach ($userName in $userFolders) {
$folderName = Get-ChildItem -Path "C:\Users\$userName\AppData\Local\Apps\2.0" -Directory -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match '[A-Za-z0-9]{8}\.[A-Za-z0-9]{3}' } |
Select-Object -ExpandProperty Name
# do something with this variable
Write-Host "C:\Users\$userName\AppData\Local\Apps\2.0\$folderName"
}
Some RegEx could do the trick:
$str = "C:\Users\user\AppData\Local\Apps\2.0\5J91Q4CX.C10"
$str -match '.*\\(.*)$'
$matches[1] # 5J91Q4CX.C10
.*\\(.*)$ matches all chars after the last dash \ and before the end of the line $
not sure what you are really trying to do... you could do a directory search through the C:\Users to report back on all subfolders and then a Foreach loop to go through each subfolder and create the file wanted in the destination etc, something like:
$FOLDERS = Get-ChildItem C:\Users -Directory
FOREACH ($FOLDER in $FOLDERS) {
#WHATEVER YOU WANT TO DO
}

User Directory Identification

I need to create a script to iterate through a list of user samaccountnames and identify network directories matching their samaccountname on the network. It doesn't seem to work though. Users home folders on the network use their samaccountname in the path. Here is what I have so far:
$userList = "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_SamAccountName.csv"
$userDirectory = foreach ($user in $userList)
{
Get-ChildItem -Path "\\ceoii\" -Directory -Recurse | ? {}
}
Export-Csv -Path "C:\Users\sfp01\My
Documents\Data_Deletion_Testing\User_Directory.csv"
First, you need to import the csv as your first line just saves the location of the file in the variable rather than the contents of the file.
Second, you didn't provide the column name of the csv file that contains the user's saMAccountName. You'll need to set up your Where-Object to filter using that information. I am using -match on saMAccountName, but edit this to reflect your requirements.
And I don't think that \\servername\ isn't a valid share name, it should be a share like \\servername\share\ If you want to get all the shares from a server you could enumerate them with something like this invoke-command -ComputerName ceoii -ScriptBlock {Get-SmbShare}
You also probably want to only pull the list of folders once and then filter for each user.
Lastly, you save the information in $userDirectory so you'll want to pipe that information into your export-csv.
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv'
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userDirectory = foreach ($user in $userList) {
$folders | Where-Object {$_.name -match $user.saMAcountName}
}
$userDirectory | Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'
More efficient than that would be to use -in or -contains if you know that the folder names exactly match.
$folders = Get-ChildItem -Path "\\ceoii\sharename" -Directory -Recurse
$userList = Import-CSV 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_SamAccountName.csv' |
Select-Object -ExpandProperty saMAccountName
$folders |
Where-Object {$_.name -in $userList} |
Export-Csv -Path 'C:\Users\sfp01\My Documents\Data_Deletion_Testing\User_Directory.csv'