# Validating data prior to changing values in CSV file

**URL:** <https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830>\
**Category:** PowerShell Help\
**Created:** [March 15, 2022, 7:04pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830 "2022-03-15T19:04:15Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 15, 2022, 7:04pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/1 "2022-03-15T19:04:15Z")

</div>

Hello,

I have a CSV file that contains a list of Windows operating systems that need to be updated often using new folder names created during the update process.

For example, when `Windows 11 Pro x64 21H2 22000.318` is updated offline, the updated version is placed into a new folder. That new folder name will either have an updated **Build number** , or a **timestamp** appended to the original name automatically: For example: `Windows 11 Pro x64 21H2 22000.556` or `Windows 11 Pro x64 21H2 22000.556 2203140144`.

I was able to figure out how to grab those new folder names, and sort them in order before plugging them into the CSV file using the following code:

```auto
### Update CSV with new folder names ###

# Global Variables
$OSMedia = "D:\OSD\Builder\OSMedia\"
$csv_file = "D:\OSD\Builder\List-SourceNames.csv"
$csv_file_old = "D:\OSD\Builder\List-SourceNames-OLD.csv"

# Backup CSV File
Copy-Item $csv_file -Destination $csv_file_old -Force

# Prompt for latest number of folders to get
$num = Read-Host "Enter number of latest folders"

# Create $latest folder names array (excluding "build" folders)
$latest = (Get-ChildItem $OSMedia -Exclude "build*" | Where { $_.PSIsContainer } | Sort CreationTime -Descending | Select -First $num | Select-Object Name).Name
$latest = $latest | Sort-Object

# Replace osd_names in CSV with $latest folder names
$osd_names = Import-CSV "$csv_file_new"
$num = 0
foreach ($osd_name in $osd_names)
    {
    $osd_name.osd_name = $osd_name.osd_name.replace($osd_name.osd_name,$latest[$num])
    $num = $num+1
    }
$osd_names | Export-CSV "$csv_file" -Force -NoTypeInformation -Encoding ASCII

```

I’m currently working with six operating systems. If all six are updated, then using my above script will work perfectly. However, if I have fewer than six, I need to update the CSV file manually because the above script doesn’t know how to tell a given value to only replace another given value.

I’m wondering if I could use the first part of the folder names that never change, such as `Windows 11 Pro x64 21H2`. Based on this value, the script would (hypothetically) know to replace `Windows 11 Pro x64 21H2 22000.318` with `Windows 11 Pro x64 21H2 22000.556`.

CSV column contents:

```auto
osd_name
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566
Windows 10 Pro for Workstations x64 21H2 19044.1288
Windows 11 Pro for Workstations x64 21H2 22000.318
Windows 11 Pro x64 21H2 22000.318
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000

```

I’m playing around with the `-split` option, but I’m not sure this will help me achieve my objective.

```auto
$split_names = "Windows 11 Pro x64 21H2 22000.556"
$a = $split_names.split(".")[0]
$a

```

**Output:** `Windows 11 Pro x64 21H2 22000`

Is there a way that I can use a portion of this string `Windows 11 Pro x64 21H2 22000.318` or another value in my csv file to tell PowerShell what value to replace it with?

Old Name: `Windows 11 Pro x64 21H2 22000.318`  
New Name: `Windows 11 Pro x64 21H2 22000.556`

I have a column that I use for the base name for each OS, such as `Windows 11 Pro`.

Could someone point me in the right direction so I can take a stab at it?

Thank you…

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 15, 2022, 7:51pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/2 "2022-03-15T19:51:38Z")

</div>

Updated thought:

Perhaps I could use an IF statement along with the -like and -replace…?  
My PowerShell is running updates now, so it will be tied up for a few hours (it’s Patch Tuesday), but when I get a chance later, it would be nice to know if I’m on the right track with that thought.

---

<div class="post-metadata">

**Author:** ![matt-bloomfield](https://avatars.discourse-cdn.com/v4/letter/m/dec6dc/32.png) [@matt-bloomfield](https://forums.powershell.org/u/matt-bloomfield)\
**Post date:** [March 15, 2022, 10:14pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/3 "2022-03-15T22:14:26Z")

</div>

I’m not sure if I fully understood what you’re trying to do but I think something like this would work:

```auto
$data = @'
osd_name
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566
Windows 10 Pro for Workstations x64 21H2 19044.1288
Windows 11 Pro for Workstations x64 21H2 22000.318
Windows 11 Pro x64 21H2 22000.318
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000
'@

$csv = $data | ConvertFrom-Csv

$latest = @(
    'Windows 10 Pro for Workstations x64 21H2 19044.3000'
    'Windows Server 2022 Datacenter x64 Dev 22509.1500'
)

foreach ($update in $latest) {
    
    $update -match '(.+)(\d{5}\.\d+$)'
    $entry = ($csv.osd_name | Where-Object {$_ -like "$($matches[1])*"}) 
    $index = $csv.osd_name.IndexOf($entry)
    $csv[$index].osd_name = $csv[$index].osd_name -replace '(\d{5}\.\d+$)',$matches[2]

}

```

What it does:

The regular expression uses two capture groups  
1:`(.+)`  
2: `(\d{5}\.\d+$)`  
which populates the automatic variable `$matches` with 2 entries (actually more, but we’ll ignore the details). `$matches[1]` will refer to everything up to the 5 digit number, `$matches[2]` will refer to the 5 digit number to the end of the string.

We append the wildcard character ‘\*’ to the first match, to find the entry in the CSV; then we get the entry’s index number so we can update it directly.

Finally, we look for the same pattern in the entry to find and replace the version number.

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 15, 2022, 11:22pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/4 "2022-03-15T23:22:32Z")

</div>

Hello @matt-bloomfield,

Thanks for taking a look into this for me. I ran your code, and it came back with:

```auto
True
True

```

I updated your $latest array with my values:

```auto
$latest = @(
    'Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586'
    'Windows 10 Pro for Workstations x64 21H2 19044.1586'
    'Windows 11 Pro for Workstations x64 21H2 22000.556'
    'Windows 11 Pro x64 21H2 22000.556'
    'Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000 2203140144'
    'Windows Server 2022 Datacenter x64 Dev 22509.1000 2203140148'
)

```

And it came back with:

```auto
True
True
True
True
False
False

```

I modified your code some more so that it would import my CSV file and import the `$latest` content as well to see if any changes would be made to the CSV file.

```auto
$data = Import-CSV "D:\OSD\Builder\List-SourceNames-NEW.csv"
$latest = Get-Content "D:\OSD\Builder\OSMedia-Latest_.txt"
foreach ($update in $latest) {
    $update -match '(.+)(\d{5}\.\d+$)'
    $entry = ($csv.osd_name | Where-Object {$_ -like "$($matches[1])*"}) 
    $index = $csv.osd_name.IndexOf($entry)
    $csv[$index].osd_name = $csv[$index].osd_name -replace '(\d{5}\.\d+$)',$matches[2]
}

```

Because I’m importing the CSV file in place of the `$data` array, I tested this without the `$csv = $data | ConvertFrom-Csv` line.

I then replaced your `$latest` array with mine by importing the contents from the Text file using `$latest = Get-Content "D:\OSD\Builder\OSMedia-Latest_.txt"` as seen in the code above.

After running this, I still get the same output with 4 `True`(s) and 2 `False`(s). Interestingly, I didn’t see any changes to the CSV file.

Because I didn’t use your `$csv = $data | ConvertFrom-Csv`, I replaced all of the `$csv` variables to `$data`:

```auto
foreach ($update in $latest) {
    $update -match '(.+)(\d{5}\.\d+$)'
    $entry = ($data.osd_name | Where-Object {$_ -like "$($matches[1])*"}) 
    $index = $data.osd_name.IndexOf($entry)
    $data[$index].osd_name = $data[$index].osd_name -replace '(\d{5}\.\d+$)',$matches[2]
}

```

I get the same results as I’m sure is expected.

I still need to absorb the topic of regular expressions. It’s going to take me some time for it to really sink in. I’ll look for some online videos that show how it works. I read Microsoft’s [about\_Regular\_Expressions](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.2), but it seems a bit oversimplified considering I can’t figure out how to apply it to my situation. It’s also where I came across `-split` which I was hoping would be my saving grace. 🙂

Any thoughts on why the CSV file isn’t getting any changes? I’m also curious about those two `False` values being returned.  
I’ll try to figure out how I can experiment with a single string, which I think may help me grasp this concept faster.

As for my end goal. I’ll provide an image for a better visual.

 ![osd latest folders and csv](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/2X/b/bbaf282ce645d1e848b0b7f14c2d65ab5290b4c4.jpeg)

Based on the data that we’re comparing in your sample script, I need to take the values from the `OSMedia-Latest_.txt` file and use that to replace the values in the CSV file under `osd_name`. Although they are in perfect order in the Text file, there will be times when I have fewer than 6 entries and probably in a different order. The CSV file is always in the same order though.

Thank you for your sample code. I will continue to play with and revisit the topic of learning how to better understand PowerShell’s regular expressions.

Thank you…

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [March 16, 2022, 12:19am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/5 "2022-03-16T00:19:16Z")

</div>

I have a few thoughts on this.

1. You are way overcomplicating this.
2. You should never have to manually input how many new folders.

First thing, let’s get our list of OSMedia. If there are more folders here other than the “new” folders - you should figure out how to properly identify the new ones. (could easily use the existing csv to compare to entire list to find which are new, or perhaps use a datetime as the filter) I’m going to work off the assumption that the folders in this directory are the folders that you need to match your csv.

```auto
$OSMedia = "D:\OSD\Builder\OSMedia\"
$latest = Get-ChildItem $OSMedia -Exclude "build*" -Directory |
    Sort-Object -Property Name | Select-Object -ExpandProperty Name

```

Now we get our CSV data

```auto
$csv_file = "D:\OSD\Builder\List-SourceNames.csv"
$osd_names = Import-CSV "$csv_file"

```

Now process the new folders, updating the csv if there is a match

```auto
foreach($name in $latest){
    Write-Host Processing new folder $name -ForegroundColor Cyan

    # take the folder name and replace everything from the space and build number to the end
    # Windows 11 Pro for Workstations x64 21H2 22000.318 becomes Windows 11 Pro for Workstations x64 21H2
    $basename = $name -replace '\s\d{5}.+$'

    # try to find a line in the csv that matches this basename
    $match = $osd_names | Where-Object osd_name -match $basename
    if($match.count -gt 1){
        Write-Warning "More than one csv entry matched $basename"
    }
    elseif($match.count -eq 1){
        Write-Host "Updating CSV entry $($match.osd_name) to $name" -ForegroundColor Cyan
        $match.osd_name = $name
    }
    else{
        Write-Host No entry in CSV matching $basename
    }
}

```

Now you can look at your csv to confirm it’s changed before export

```auto
$osd_names | Format-Table

```

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 16, 2022, 3:56am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/6 "2022-03-16T03:56:26Z")

</div>

Hello @krzydoug,

This is pretty amazing work with the “Processing New Folders to Match”. I was analyzing the `$basename = $name -replace '\s\d{5}.+$'` portion and it makes sense after cross-referencing Microsoft’s [about\_Regular\_Expressions](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.2).

I can see where the `$basename` becomes the truncated name after stripping the space (\s), the first 5 numbers (\d{5}) of the Build, along with the dot (.+) and if I recall correctly, the ($) represents everything to the end of the string; or is it (+$) that does that?

One thing to note is that although the code for processing the **New Folders to Match** is producing the correct _truncated_ names, they don’t seem to want to match. The output after running your code shows they match, but the output is returning:

`No entry in CSV matching…`

```auto
Processing new folder Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586
No entry in CSV matching Windows 10 Enterprise LTSC 2021 x64 21H2
Processing new folder Windows 10 Pro for Workstations x64 21H2 19044.1586
No entry in CSV matching Windows 10 Pro for Workstations x64 21H2
Processing new folder Windows 11 Pro for Workstations x64 21H2 22000.556
No entry in CSV matching Windows 11 Pro for Workstations x64 21H2
Processing new folder Windows 11 Pro x64 21H2 22000.556
No entry in CSV matching Windows 11 Pro x64 21H2
Processing new folder Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000 2203140144
No entry in CSV matching Windows Server 2022 Datacenter Desktop Experience x64 Dev
Processing new folder Windows Server 2022 Datacenter x64 Dev 22509.1000 2203140148
No entry in CSV matching Windows Server 2022 Datacenter x64 Dev

```

I get the same results when using `$osd_names` and `$latest` as arrays versus importing the data:

```auto
# OLD Values: CSV File Column 'osd_name'
$osd_names = (
    'Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566',
    'Windows 10 Pro for Workstations x64 21H2 19044.1526',
    'Windows 11 Pro for Workstations x64 21H2 22000.493',
    'Windows 11 Pro x64 21H2 22000.493',
    'Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000',
    'Windows Server 2022 Datacenter x64 Dev 22509.1000'
)

# NEW Values: Latest Folders
$latest = (
    'Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586',
    'Windows 10 Pro for Workstations x64 21H2 19044.1586',
    'Windows 11 Pro for Workstations x64 21H2 22000.556',
    'Windows 11 Pro x64 21H2 22000.556',
    'Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000 2203140144',
    'Windows Server 2022 Datacenter x64 Dev 22509.1000 2203140148'
)

```

I noticed that `$osd_names | Format-Table` outputs the old vaues from the CSV file.

```auto
PS C:\Windows\system32> $osd_names | Format-Table
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566
Windows 10 Pro for Workstations x64 21H2 19044.1526
Windows 11 Pro for Workstations x64 21H2 22000.493
Windows 11 Pro x64 21H2 22000.493
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000

```

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 16, 2022, 4:05am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/7 "2022-03-16T04:05:50Z")

</div>

I noticed that the `elseif($match.count -eq 1)` is what I’m expecting to happen considering that means that the `$match.count` is equal to only 1 object in the CSV file. When I call on `$match.count`, it shows a value of `0`.

```auto
PS C:\Windows\system32> $match.count
0

```

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [March 16, 2022, 4:14am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/8 "2022-03-16T04:14:12Z")

</div>

Is osd\_name the correct property name?

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 16, 2022, 4:37am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/9 "2022-03-16T04:37:14Z")

</div>

Correct. `osd_name` is the Property name for the list of OS Names in the CSV file.  
I double checked by importing the CSV file and running:

```auto
$osd_names | gm

```

Which outputs in part, the following:

```auto
Name MemberType Definition                                                                                                    
---- ---------- ----------                                                                                                    
Equals Method bool Equals(System.Object obj)                                                                                
GetHashCode Method int GetHashCode()                                                                                             
GetType Method type GetType()                                                                                                
ToString Method string ToString()                                                                                             
osd_builds NoteProperty string osd_builds=D:\OSD\Builder\OSBuilds                                                                     
osd_import NoteProperty string osd_import=D:\OSD\Builder\OSImport                                                                     
osd_media NoteProperty string osd_media=D:\OSD\Builder\OSMedia                                                                       
osd_name NoteProperty string osd_name=Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566                                           

```

Thanks…

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [March 16, 2022, 4:53am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/10 "2022-03-16T04:53:28Z")

</div>

What if you try changing it to

```auto
Where-Object osd_name -match “$basename”

```

Or

```auto
Where-Object {$_.’osd_name’ -match $basename}

```

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 16, 2022, 5:04am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/11 "2022-03-16T05:04:14Z")

</div>

@krzydoug,

Thanks for double checking this, but unfortunately both of those changes result in the same output.

```auto
Processing new folder Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586
No entry in CSV matching Windows 10 Enterprise LTSC 2021 x64 21H2
...

```

---

<div class="post-metadata">

**Author:** ![matt-bloomfield](https://avatars.discourse-cdn.com/v4/letter/m/dec6dc/32.png) [@matt-bloomfield](https://forums.powershell.org/u/matt-bloomfield)\
**Post date:** [March 16, 2022, 8:44am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/12 "2022-03-16T08:44:58Z")

</div>

The order should not matter, for each updated value in `$latest`, the script checks if there’s a matching value in the csv data.

My code updates the ‘copy’ of the csv file (my variable `$csv`) in memory, which you can view by putting `$csv` at the bottom to see the changes have been made.

To update the actual file, you would need to use `Export-CSV`.

To suppress the `True/False` output, you can redirect the output:

```auto
$update -match '(.+)(\d{5}\.\d+$)' | Out-Null

```

Can you share the full code you made after adapting my version?

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 16, 2022, 6:53pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/13 "2022-03-16T18:53:18Z")

</div>

Hello @matt-bloomfield,

I ran your code again and then called `$csv` to see what changes were being stored in memory. It turns out those two `False` values were for the two Server 2022 operating systems which show the old values, while the other 4 show the updated values.

It appears the `$update -match '(.+)(\d{5}\.\d+$)'` is having issues between the Client and Server operating systems due to their naming just prior to the -matching criteria:

- The `True` values end with `21H2`
- The `False` values end with `DEV`; no number at the end.

```auto
$csv

True
True
True
True
False
False

osd_name                                                            
--------                                                            
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586                 
Windows 10 Pro for Workstations x64 21H2 19044.1586                 
Windows 11 Pro for Workstations x64 21H2 22000.556                  
Windows 11 Pro x64 21H2 22000.556                                   
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000

```

As for the modifications to your code; those were done just for testing. The only one that produces similar results when I imported my CSV file was the following:

**Note** : The only changes made were omitting `$csv = $data | ConvertFrom-Csv` and changing all `$csv` entries to `$data`.

```auto
$data = Import-CSV "D:\OSD\Builder\List-SourceNames-OLD.csv"
$latest = Get-Content "D:\OSD\Builder\OSMedia-Latest-1.txt"

foreach ($update in $latest) {
    
    $update -match '(.+)(\d{5}\.\d+$)'
    $entry = ($data.osd_name | Where-Object {$_ -like "$($matches[1])*"}) 
    $index = $data.osd_name.IndexOf($entry)
    $data[$index].osd_name = $data[$index].osd_name -replace '(\d{5}\.\d+$)',$matches[2]
}
$data

```

> [@matt-bloomfield](#):
>
> The order should not matter, for each updated value in `$latest` , the script checks if there’s a matching value in the csv data.

- I tested the ordering by disordering my `$latest` array values and they lined up correctly as you stated.
- No issues with exporting, except the two `False` values failing to match.
- I piped `Out-Null` as you suggested, but will leave it commented out for the time being.  
`$update -match '(.+)(\d{5}\.\d+$)' #| Out-Null`

Thank you…

---

<div class="post-metadata">

**Author:** ![matt-bloomfield](https://avatars.discourse-cdn.com/v4/letter/m/dec6dc/32.png) [@matt-bloomfield](https://forums.powershell.org/u/matt-bloomfield)\
**Post date:** [March 16, 2022, 9:50pm UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/14 "2022-03-16T21:50:41Z")

</div>

OK, I missed that you sometimes have the date at the end of the latest version. That means that this:

```auto
$update -match '(.+)(\d{5}\.\d+$)

```

won’t match the update because `$` asserts the end of the line.

Removing the `$` should resolve the problem:

```auto
$data = Import-CSV E:\Temp\Files\List-SourceNames-OLD.csv
$latest = Get-Content E:\Temp\Files\latest.txt

foreach ($update in $latest) {
    
    $update -match '(.+)(\d{5}\.\d+)' | Out-Null
    $entry = ($data.osd_name | Where-Object {$_ -like "$($matches[1])*"}) 
    $index = $data.osd_name.IndexOf($entry)
    $data[$index].osd_name = $data[$index].osd_name -replace '(\d{5}\.\d+)',$matches[2]

}

$data

```

Output:

```auto
src_name osd_name
-------- --------
Windows 10 Enterprise LTSC 2021 Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586
Windows 10 Pro for Workstations Windows 10 Pro for Workstations x64 21H2 19044.1586
Windows 11 Pro for Workstations Windows 11 Pro for Workstations x64 21H2 22000.556
Windows 11 Pro Windows 11 Pro x64 21H2 22000.556
Windows Server 2022 Datacenter (Desktop Experience) Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1200
Windows Server 2022 Datacenter Windows Server 2022 Datacenter x64 Dev 22509.1000

```

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 17, 2022, 1:52am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/15 "2022-03-17T01:52:43Z")

</div>

Hello @matt-bloomfield,

Dropping the `$` certainly changed the results for the two Server entries to `True`.  
Using the original arrays:

```auto
$csv

True
True
True
True
True
True

osd_name                                                            
--------                                                            
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586                 
Windows 10 Pro for Workstations x64 21H2 19044.1586                 
Windows 11 Pro for Workstations x64 21H2 22000.556                  
Windows 11 Pro x64 21H2 22000.556                                   
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000  

```

Unfortunately, the output for the two servers at the bottom of the list have their (new value) Timestamps removed.

It appears from your output that you are using my Source Names for the CSV input instead of the `osd_name`’s…?

Just curious. I provided those in the screenshot to see if it was possible to just match those with the `$latest` values considering they don’t have all that extra information behind it.

Would that make it easier or worse?

Or do you think the value should be compared at the `" x64"` instead of the build number…?

I tried the following to no avail:  
`$update -match '\s[x]\d{2}'` comes back `True` but returns all of the old values, but for some reason truncates the last one in the list to: `Windows Server 2022 Datacenter x64 Dev`

Using the $ at the end returns all `False`, so no changes are applied.  
`$update -match '\s[x]\d{2}$'`

I thought I could start with the space `\s`, followed with the letter `[x]` and the trailing 2 digits `\d{2}`.

Considering there is only one “x”, I thought I could use that as the starting point instead of the build numbers dot.

Even after reading through this article on how RegEx works, it’s terribly confusing still.  
[PowerShell Match | How do Match Operators work in PowerShell? (educba.com)](https://www.educba.com/powershell-match/)

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [March 17, 2022, 2:47am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/16 "2022-03-17T02:47:19Z")

</div>

Try removing the $ from my suggestion. Regular expressions are very specific so if you show some text but are working with different text, you can expect suggestions not to work.

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 17, 2022, 3:16am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/17 "2022-03-17T03:16:47Z")

</div>

Hi @krzydoug ,

I dropped the `$` from your code as requested. Unfortunately, the results were the same:  
`$basename = $name -replace '\s\d{5}.+'`

```auto
Processing new folder Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1586
No entry in CSV matching Windows 10 Enterprise LTSC 2021 x64 21H2
...

```

`$osd_names | Format-Table` Outputs the old values still:

```auto
Windows 10 Enterprise LTSC 2021 x64 21H2 19044.1566
Windows 10 Pro for Workstations x64 21H2 19044.1526
Windows 11 Pro for Workstations x64 21H2 22000.493
Windows 11 Pro x64 21H2 22000.493
Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000
Windows Server 2022 Datacenter x64 Dev 22509.1000

```

Is it possible to modify the `-match` or `-replace` criteria to truncate it before the "` x64`" instead of the build.#?

I’m still reading up on that and playing around with some experiments, but nothing promising so far.

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [March 17, 2022, 3:57am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/18 "2022-03-17T03:57:01Z")

</div>

Then we either have the wrong property names, wrong values, or something different that we can’t see.

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 17, 2022, 4:16am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/19 "2022-03-17T04:16:03Z")

</div>

Perhaps we can slim down your original code and me ruling out the `Import-CSV` used to populate the `$osd_names` array (old values) and the `Get-Content` used to populate the `$latest` array (new values).

```auto
# OLD Values: CSV File Column 'osd_name'
$osd_names = (
    'Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000',
    'Windows Server 2022 Datacenter x64 Dev 22509.1000'
)

# NEW Values: Latest Folders
$latest = (
    'Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000 2203140144',
    'Windows Server 2022 Datacenter x64 Dev 22509.1000 2203140148'
)

foreach($name in $latest){
    Write-Host Processing new folder $name -ForegroundColor Cyan

    # take the folder name and replace everything from the space and build number to the end
    # Windows 11 Pro for Workstations x64 21H2 22000.318 becomes Windows 11 Pro for Workstations x64 21H2
    $basename = $name -replace '\s\d{5}.+'

    # try to find a line in the csv that matches this basename
    $match = $osd_names | Where-Object osd_name -match “$basename”
    if($match.count -gt 1){
        Write-Warning "More than one csv entry matched $basename"
    }
    elseif($match.count -eq 1){
        Write-Host "Updating CSV entry $($match.osd_name) to $name" -ForegroundColor Cyan
        $match.osd_name = $name
    }
    else{
        Write-Host No entry in CSV matching $basename
    }
}

$osd_names | Format-Table

```

Using just the two values with timestamps, do you think starting the `match` with the "` x64`" portion in the name would help? I’m still trying to wrap my head around RegEx and all the rules to figure out how I can do that, but so far no luck.

I’m reading here at the moment: [Regular Expression Language - Quick Reference | Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference)

Damn if it ain’t extremely confusing… but I’m determined to make some sense out of… _eventually_. 😬

---

<div class="post-metadata">

**Author:** ![zero269](https://avatars.discourse-cdn.com/v4/letter/z/da6949/32.png) [@zero269](https://forums.powershell.org/u/zero269)\
**Post date:** [March 17, 2022, 5:03am UTC](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830/20 "2022-03-17T05:03:38Z")

</div>

Interestingly enough, I was able to get the `-match` to truncate from the "` x64`" to the end using either of these first two (RegEx) expressions. The third one didn’t trim anything at all.

```auto
$basename = $name -replace '\s[x]\d{2}.+$'
$basename = $name -replace '\s[x]\d{2}.+'
$basename = $name -replace '\s[x]\d{2}'

```

Output:

```auto
Processing new folder Windows Server 2022 Datacenter Desktop Experience x64 Dev 22509.1000 2203140144
No entry in CSV matching Windows Server 2022 Datacenter Desktop Experience
Processing new folder Windows Server 2022 Datacenter x64 Dev 22509.1000 2203140148
No entry in CSV matching Windows Server 2022 Datacenter

```

Unfortunately, this didn’t make any difference with the `$match.count` which always remains at `0`, which means it will never be `-eq 1` here:

```auto
elseif($match.count -eq 1){
        Write-Host "Updating CSV entry $($match.osd_name) to $name" -ForegroundColor Cyan
        $match.osd_name = $name
    }

```

[Next page](https://forums.powershell.org/t/validating-data-prior-to-changing-values-in-csv-file/18830.md?page=2)
