John Balan John Balan - 4 months ago 14
PowerShell Question

PowerShell reading a list of text files in a folder

We need to get a list of workstation ids for a set of users. We modified the startup script to run a batch file that dumps the info we need to a file share in the following method:

username.txt

Edit: Here is a sample of the text file (there are 2000 users, so we will have 2000 files in time)


Workstation1
Workstation2
CitrixServer1
Workstation1
Workstation1



We will have duplicates because they will login multiple times.

This file has the list of machines (workstation and citrix servers that the user has logged into). Now I am trying to extract the information in a meaningful manner (there are over 1300 files and the final count will be around 2000). So far this is what I have:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# this is the path for the share
$SearchFolder = "\\server\Users\*.txt"

# Search each txt file in the path and store all of the lines and filenames that don't match the pattern

$File = Select-String -Path $SearchFolder -Pattern %CLIENTNAME%,"ECHO is on", "server*","vs*","ctx*" -NotMatch | select line, filename

$File


What this gives me is the following:


Workstation1 User1
Workstation2 User2
Workstation3 User3
Workstation4 User3
Workstation4 User3



What I want to do is get a list of unique workstations that a user has logged in to.


User1
Workstation1

User2
Workstation2

User3
Workstation3
Workstation4



How can I do this?

Answer

The output that you've stored in $File should already be an array of objects, each of which has a property called .line (which is the computer name) and a property called .filename (which is the user name).

By grouping them by user, you can get a list of workstations, and from there you can make that list unique:

$groups = $File | Group-Object filename

This gives you a new type of object, where the .Name property refers to the element being grouped by, in this case the filename (which is the user name). The .Group property is the original object(s).

So from there, you can iterate over the groups and get the workstations for each one:

$all = $groups | ForEach-Object {
    $user = [System.IO.Path]::GetFileNameWithoutExtension($_.Name)
    $computers = $_.Group.line | Sort-Object | Select-Object -Unique
    [PSCustomObject]@{
        User = $user
        Computers = $computers
    }
}

Now $all will contain an array of objects, where each object represents a user, with an array of the computers. You can format that however you like.

Comments