How do I concatenate a string within a loop with PowerShell? - string

The command
Get-VM | Where {$_.PowerState -eq "PoweredOn"} | Select Name,VMHost | Where {$_ -match "abc" -or $_ -match "def"} | foreach{$_.Name} | Out-File output.txt
writes a list to output.txt where only the column Name will be printed in the form:
a
b
c
...
Now what I want to achieve is to append ,xxx to each line in some sort of loop, so that I get the following:
a,xxx
b,xxx
c,xxx
...
I tried to append the string, but this doesn't seem to work:
Get-VM | Where {$_.PowerState -eq "PoweredOn"} | Select Name,VMHost | Where {$_ -match "abc" -or $_ -match "def"} | foreach{$_.Name} | Out-File output.txt | Add-Content output.txt ",xxx"
I'm really not familiar with PowerShell, and I did not find a way to concatenate ,xxx.
In my case it is essential to do the concatenation within a loop, not with a file operation afterwards.

Instead of foreach { $_.Name }, write foreach { "$($_.Name),xxx" }

Related

Linux Bash Shell Command in Windows Powershell

So the following command in Linux is to order a Nginx access.log file by those making the most requests.
'awk '{ print $1 }' access.log | uniq -c | sort -nr | more'
What it the equivalent for this command in Windows Powershell ?
Get-Content access.log | ForEach-Object { $_.split()[0] -as [IPAddress] } | Sort-Object | Select-Object -Unique -ExpandProperty IPAddressToString
or
gc access.log |%{ $_.Split()[0] -as [IPAddress] } | sort -U |%{ "$_" }
Read the file
Process it line by line
Split on spaces and take the first element
Cast it to an IPAddress type so it will sort numerically
Sort and deduplicate one way or another
Get the string representation of the [IPAddress] back out
NB. your code doesn't do what you claim; you need to be sorting first, before uniq, as it only removes consecutive duplicates, not all duplicates.

Splitting Export large CSV files via Powershell

Like everyone know excel has got max rows 1048574. My question is :when the max row is reached, then move to a new CSV file I have tried something no luck I can't figure it out.
$RootFolder = Get-Content "c:\DRIVERS\myfile.txt"
foreach ($arrayOfPaths in $RootFolder){
$csv = $arrayofPaths -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
$path = $_.FullName
Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
Export-Csv $csv -Append -NoType
}
}
Last Update :
$RootFolder = Get-Content "c:\DRIVERS\myfile.txt"
foreach ($arrayOfPaths in $RootFolder){
$csv = $arrayofPaths -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'
$csvIndex = 1
$maxRows = 1000000
$rowsLeft = $maxRows
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
#$csv = $_.FullName -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'# <- construct CSV path here
$path = $_.FullName
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
if ($thisCSV.count -lt $rowsLeft) {
$thisCSV | Export-Csv $csv -append -noType
$rowsLeft -= $thisCSV.count
} else {
$thisCSV[0..($rowsLeft - 1)] | Export-Csv $csv -append -noType
$csvIndex++
$csv = $csv -replace '\.csv$', "$csvIndex.csv"
if ($thisCSV.count -gt $rowsLeft) {
$thisCSV[$rowsLeft..($thisCSV.count - 1)] | Export-Csv $csv -append -noType
}
$rowsLeft = $maxRows - ($thisCSV.count - $rowsLeft)
}
}
}
Do ConvertTo-Csv in a temporary variable, add up its .Count property until the split point is reached, then split the CSV array to a new file with a new name that will be used from this point on.
Below is a simplified example that assumes no single CSV can exceed 1000000 rows.
$csv = .............
$csvIndex = 1
$maxRows = 1000000
$rowsLeft = $maxRows
...........
$thisCSV = Select-Object ........ |
ConvertTo-Csv
if ($thisCSV.count -lt $rowsLeft) {
$thisCSV | Export-Csv $csv -append -noType
$rowsLeft -= $thisCSV.count
} else {
$thisCSV[0..($rowsLeft - 1)] | Export-Csv $csv -append -noType
$csvIndex++
$csv = $csv -replace '\.csv$', "$csvIndex.csv"
if ($thisCSV.count -gt $rowsLeft) {
$thisCSV[$rowsLeft..($thisCSV.count - 1)] | Export-Csv $csv -append -noType
}
$rowsLeft = $maxRows - ($thisCSV.count - $rowsLeft)
}

Can you pass a variable as a parameter to Powershell's Select-String

I have a multiline string that I want to filter with 'Select-String'
echo $foo
bar
buzz
If I use select-string with a string parameter, it works fine
echo $foo | Select-String 'bar'
bar
If I try and replace the string selection with a variable, nothing is returned.
$variable = 'bar'
echo $foo | Select-String $variable
How do you pass a variable to Select-String ?
Here is every syntax I've tried
echo $foo | Select-String $variable
echo $foo | Select-String "$variable"
echo $foo | Select-String "$(variable)"
echo $foo | Select-String "$($variable)"
echo $foo | Select-String $($variable)
$variable is a string
$variable.getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
Using a variable works for me:
> $needle = 'Import' ; #( 'fu', 'bar', 'Import' ) | Select-String $needle
Import
Check that $foo actually contains the value in $variable. Check that you're actually piping something to Select-String (sometimes I forget to type a | character). Validate all your assumptions.

Powershell - Find and Replace

I've written the below:
$Path = "C:\"
$Folders = Get-ChildItem $Path | Where-Object {$_.mode -match "d"}
$FolderName = #()
$Folders | ForEach-Object { $FolderName += $_.name }
ForEach ($Name in $FolderName) {
$File = "C:\$Name\file.xaml"
$Content = Get-Content $File
$A = "ValueA"
$B = "ValueB"
$C = "ValueC"
$D = "ValueD"
$Content | ForEach-Object {$_ -Replace $A, $B} | Set-Content $File
$Content | ForEach-Object {$_ -Replace $C, $D} | Set-Content $File
}
However, the first find and replace does not work. I thought it was because the actual string I'm looking for is quite large, but if I change nothing in the program and then comment out the second find and replace operation, the first one starts to work. Can anyone spot why this is please? Many Thanks!
You need to refresh $Content before doing the second find and replace. At the moment, you're setting the content of the file in the first call to Set-Content, but the variable $Content still contains the old contents of the file. If you call $Content = Get-Content $File again before doing the second call, you should be golden.
Assuming your issue is not that the values overlap eachother your are writing the same source content back to file. You should combine the two Set-Content lines.
$Content | ForEach-Object {$_ -Replace $A, $B -Replace $C, $D} | Set-Content $File

Powershell extracting IIS Bindings

I have an Excel spreadsheet that has about 190 lines worth of IIS bindings. What I need to do is go line by line and get each binding from the line.
Example from one line could be:
SITE "Gateway"
(id:1,bindings:http/192.168.1.1:80:www.sample.test.com,http/192.168.1.1:80:sample.test.com,https/192.168.1.1:443:,net.tcp/808:,net.pipe/,net.msmq/localhost,msmq.formatname/localhost,state:Started)
So I would need to seperate out the two webpages, www.sample.test.com and sample.test.com. Then what I wanted to do was do an nslookup on each webpage that is pulled out from each line.
I have gotten as far as going line by line and getting each set of bindings using:
$worksheet = $workbook.sheets.item($sheetname1)
For ($1=0;$i -le 190;$i++) {
$a = $worksheet.Columns.Item(1).Rows.Item($i).text}
Edit:
I have added the following code and it seems to work (but is there a better way to do this?)
For ($1=0;$i -le 190;$i++) {
$a =#($worksheet.Columns.Item(1).Rows.Item($i).text)
For ($2=0;$2 -lt $a.length; $2++) {
$a[$2].split(':,')[5]
$a[$2].split(':,')[8]
$a[$2].split(':,')[11]
$a[$2].split(':,')[14]
$a[$2].split(':,')[17]
}
I got it to work with this but now my issue is that some of the lines dont have more than two host names to do the nslookup so in the output file I get extra data that I dont want
$a =#($worksheet.Columns.Item(1).Rows.Item($i).text)
For ($2=0;$2 -lt $a.length; $2++) {
$d = $a[$2].split(':,')[5] | Out-File -Filepath $outfile -append
$a[$2].split(':,')[5] | nslookup($_) | Out-File -Filepath $outfile -append
$e = $a[$2].split(':,')[8] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[8] | nslookup($_) | Out-File -Filepath $outfile -append
$f = $a[$2].split(':,')[11] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[11] | nslookup($_) | Out-File -Filepath $outfile -append
$h = $a[$2].split(':,')[14] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[14] | nslookup($_) | Out-File -Filepath $outfile -append
$j = $a[$2].split(':,')[17] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[17] | nslookup($_) | Out-File -Filepath $outfile -append
$k = $a[$2].split(':,')[20] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[20] | nslookup($_) | Out-File -Filepath $outfile -append
$l = $a[$2].split(':,')[23] |Out-File -Filepath $outfile -append
$a[$2].split(':,')[23] | nslookup($_) | Out-File -Filepath $outfile -append}

Resources