Change keywords in txt file with names taken from a txt file

Hi guys. As the title says i’m trying to alter text in a .txt file with names taken from another .txt file. I have zero experience using powershell but so far this is what i’m doing.

I’m gathering the names of folders in a directory and outputting to a .txt file like this

Get-ChildItem .\myfolder\ | ForEach-Object { $_.Name } > .\names.txt

And then I want to search for keywords in another .txt file called placeholder.txt and replace keywords (TEST-1, TEST-2, etc) with the names of the folders in names.txt. I think I want to do something like this

$filename = Get-Content “.\placeholder.txt”
$Keys = @(“TEST-1”,“TEST-2”,“TEST-3… TEST-50, etc.”)
ForEach ($Key in $Keys) {

}

But I don’t know where to go from here and how to make the script read from the names.txt file and then find and replace the keywords.

Is there some way I can do this?

 

How will you match up a keyword with a folder name, i.e. what folder does TEST-1 match?

I thought the first name in the names.txt file would be matched with the first keyword but it’s not really important to match them, only that each keyword is replaced by one folder name.

You can do something like the following:

$folders = Get-ChildItem . -Directory -Name
$keys = 1..$folders.Count | Foreach-Object { "TEST-$_" }
$file = Get-Content placeholder.txt

for ($i = 0; $i -lt $keys.Count; $i++) {
     $file[$i] = $file[$i] -replace $keys[$i],$folders[$i] 
}

 

The idea is you have the same number of folders, keys, and items in placeholder.txt. To make things easier, you can convert all of those contents to arrays and access the same index from each array as you iterate.

The idea is that

Thanks for the reply. I tried your suggestion but nothing changes in placeholder.txt. I’m not sure what -directory -name is for? Also my placeholder.txt file doesn’t have folders, only keywords (test-1, test-2 etc) which I want to replace and sometimes there will be more keywords than names in the names.txt file.

I found this answer

https://stackoverflow.com/questions/23863334/powershell-search-from-a-file-replace-into-another-file

But it has errors and I don’t know how to fix them and it gives another problem of how to populate the names.txt file in this format:

Test-1 replacement1
Test-2 replacement2

With the output from

Get-ChildItem .\myfolder\ | ForEach-Object { $_.Name } > .\names.txt

Where replacement1 is name of the folders in .\myfolder\

 

Here play with this. It may be helpful.

# Test folder, if this is a real important folder on your system - change this. 
$myfolder = 'C:\Temp\Test'

New-Item -Path C:\Temp -Name Test -ItemType Directory -ErrorAction SilentlyContinue | Out-Null

# Capture the string 'C:\Temp\Test\placeholder.txt' in this variable. 
$placeholder = Join-Path $myfolder placeholder.txt

# Create text file with test-1 through test-50 in it
1..50 | ForEach-Object {"Test-$_"} | Out-File $placeholder -Encoding utf8

# Just to know it's there...
Get-Content $placeholder | Select-Object -First 5

# Make 50 folders
1..50 | ForEach-Object {New-Item -Path $myfolder -Name "Folder-$_" -ItemType Directory} | Out-Null

# This is your line to make the names.txt
Get-ChildItem $myfolder -Directory | ForEach-Object { $_.Name } | Out-File .\names.txt

# Make a nice list we can manipulate of those names
[System.Collections.Generic.List[string]]$names = Get-Content .\names.txt

# Take one line from placeholder.txt, get a random folder name, remove that name from the list (so we do each once) and process all 50 lines capturing to a variable
$replacedvalues = Get-Content $placeholder | foreach {
    $randomfolder = Get-Random -Count 1 -InputObject $names
    $names.Remove($randomfolder) | Out-Null
    Write-Host "Replacing $_ with $randomfolder`n$($names.Count) names remaining..." -ForegroundColor Cyan
    $_ -replace $_,$randomfolder # In this basic example we could've just output $randomfolder, but since you said "replace"
}

# Cleanup
Remove-Item $myfolder -Recurse -Force

# The updated list is contained in $replacedvalues, so write it to the original placeholder file
$replacedvalues | Out-File $placeholder -Encoding utf8

Get-Content $placeholder | Select-Object -First 5

Try the following:

Get-ChildItem .\myfolder\ -Directory -Name | Set-Content names.txt
$names = Get-Content names.txt
$keys = 1..50 | Foreach-Object { "TEST-$_" }
$fileToReplace = Get-Content placeholder.txt

for ($i = 0; $i -lt $fileToReplace.Count; $i++) {
    $fileToReplace[$i] = "{0} {1}" -f $keys[$i % $keys.Count],$names[$i % $names.Count]
}
$fileToReplace | Set-Content placeholder.txt

 

Get-ChildItem -Directory parameter only returns directories and skips files. The -Name parameter only returns the Name attribute of each item. So there is no need to use Foreach-Object { $_.Name }. If you are creating names.txt with this code, I don’t see why you cannot just store the Get-ChildItem results in a variable.

The for loop will continue to loop through all items in the placeholder.txt file. Using the modulus operator %, we can conceivably iterate $i to its [int32] limit and still stay within the index range of the given arrays.

I think that I have explained what I am trying to do poorly. I have a HTML template (placeholder.txt) which has a whole bunch of placeholder/keywords (TEST-1, TEST-2, TEST-3…TEST-50 etc) which I can find and replace with the name of a folder.

This script does almost exactly what I want to do but I have to manually change “TEST-1” and “EXAMPLE” for each folder in .\myfolder\ and run it multiple times

(Get-Content -Path .\placeholder.txt) |
ForEach-Object {$_ -Replace ‘TEST-1’, ‘EXAMPLE’} |
Set-Content -Path .\placeholder.txt

I just want to read the names of the folders and then find/replace all instances of one of the placeholders/keywords starting with Test-1 and then Test-2 etc in the template with the name of a folder.

Based on your new information, you could do the following:

Get-ChildItem .\myfolder\ -Directory -Name | Set-Content names.txt
$names = Get-Content names.txt
$keys = 1..50 | Foreach-Object { "TEST-$_" }
$fileToReplace = Get-Content placeholder.txt
for ($i = 0; $i -lt $keys.count; $i++) {
    $fileToReplace = $fileToReplace -replace $keys[$i],$names[$i % $names.Count]
}
$fileToReplace | Set-Content placeholder.txt

 

Thank you so much! This works perfectly and will save me so much time :slight_smile:

Yes it’s generally a good idea to include pertinent details.