Why Write-Verbose messages don't appear from conditions - powershell

I'm trying to receive Verbose messages of every sorting step and run my script with -Verbose key, but I don't receive any verbose message from the conditionals (loops). I receive my messages only if I call them outside the conditionals. Please help
[CmdletBinding()]
param()
set-location "\test folder"
$listOfItems = Get-ChildItem | Select-Object -Property Name, Mode, LastWriteTime, #{label = "FileSize (MB)";expression = {$_.Length/1024/1024}}
$bufferItem = 0
for ($i = $listOfItems.Length - 1; $i -eq 0; $i--) {
for ($j = 0; $i -lt $i; $j++) {
if ($listOfItems[$j]."FileSize (MB)" -gt $listOfItems[$j + 1]."FileSize (MB)") {
Write-Verbose -Message "Transfer the value of the buffer variable to the element below the list"
continue
}
elseif ($listOfItems[$j]."FileSize (MB)" -lt $listOfItems[$j + 1]."FileSize (MB)") {
$bufferItem = $listOfItems[$j]
$listOfItems[$j] = $listOfItems[$j + 1]
$listOfItems[$j + 1] = $bufferItem
}
Write-Verbose -Message "Transfer the value of the buffer variable to the element below the list"
}
}

There's a bug in your inner loop condition:
for ($j = 0; $i -lt $i; $j++) {
Since $i -lt $i will never evaluate to $true, the inner loop body won't ever execute, and no Write-Verbose statement is ever reached.
Fix the loop condition and you'll find Write-Verbose works perfectly fine in conditional statements.

Related

Input string was not in a correct format in powershell

I am facing the error "Input string was not in a correct format." while using the variable in for loop.
$totalrows=$filepath |% {$n = $_; $c = 0; Get-Content -Path $_ -ReadCount 1000 |% { $c += $_.Count }; "$n; $c"}
echo $totalrows
Output is 8 and it is correct.
Used this variable in for loop:
For ($i = 0; $i -lt $totalrows; $i++) {
Write-host $i
}
but i get the error :
8" to type "System.Int32". Error: "Input string was not in a correct format."
So, I looked into SO for same questions so i found to typecast into integer:
$totalrows=$filepath |% {$n = $_; $c = 0; Get-Content -Path $_ -ReadCount 1000 |% { $c += $_.Count }; "$n; $c"}
$totalrowscast=[int]$totalrows
echo $totalrowscast
For ($i = 0; $i -lt $totalrowscast; $i++) {
Write-host $i
}
But still I am facing the same error.
You're outputting a single string containing both the path AND the row count, eg. "path; 8", which can't be converted to a numerical type, hence the error.
You don't need to manually count each chunk read by Get-Content - the cmdlet already adds a line number to each string it outputs, so you can simply discard everything but the last line and its line number will be the line count (excluding any trailing newline):
$totalrows = Get-Content $filepath |Select -Last 1 -ExpandProperty ReadCount
The ReadCount property is already an [int], so everything will start working expected, including $i -lt $totalrows

Nested while loop only runs once

I am trying to use this script to add text to every file in a folder. It is working, but only on the first file in the folder. The for statement seems to be working because it is giving an accurate count of the files in the folder, but only modifying the first file. I feel like I am missing something stupid here.
$fullPath = "M:\BHX\DrillTeqConversion"
$reader = [System.IO.File]::OpenText("M:\BHX\DrillteqConversion.txt")
$lineNumberx = 25
function get200Files($path) {
$mprFiles = #(Get-ChildItem $path -include *.mpr -Recurse)
if ($mprFiles -ne $NULL) {
$mprFileCount = 0
For ($i = 0; $i -lt $mprFiles.Length; $i++) {
$mprFileCount += 1
$thisFile = $mprFiles[$i]
while($null -ne ($line = $reader.ReadLine())) {
$textToAdd = $line
$newLineToAdd = "`n"
$fileContent = Get-Content $thisFile
$fileContent[$lineNumberx-1] += $newLineToAdd
$fileContent[$lineNumberx-1] += $textToAdd
$fileContent | set-Content $thisFile
$lineNumberx = $lineNumberx + 1
}
}
Write-Host ("A total of " + $mprFileCount + " files were converted.")
}
}
get200Files $fullPath
[System.IO.File]::OpenText("M:\BHX\DrillteqConversion.txt") with ReadLine() only allows reading through a file once. So you cannot loop through the file endlessly without reopening it or using another strategy. Code samples below have been reduced for simplicity.
for ($i = 0; $i -lt $mprFiles.Length; $i++) {
# for loop code before while loop
$reader = [System.IO.File]::OpenText("M:\BHX\DrillteqConversion.txt")
while($null -ne ($line = $reader.ReadLine())) {
# while loop code
}
# After while loop but inside of For loop
$reader.Dispose()
$reader.Close()
}
You could make a new parameter for your function and pass that into OpenText() as well.
function get200Files($path,$FileToRead) {
for ($i = 0; $i -lt $mprFiles.Length; $i++) {
# for loop code before while loop
$reader = [System.IO.File]::OpenText($FileToRead)
while($null -ne ($line = $reader.ReadLine())) {
# while loop code
}
# After while loop but inside of For loop
$reader.Dispose()
$reader.Close()
}
}
$fullPath = "M:\BHX\DrillTeqConversion"
$ReaderPath = "M:\BHX\DrillteqConversion.txt"
get200Files $fullPath $ReaderPath

Powershell - .csv split strings

I am trying to use powershell for extracting email addresses from a .csv file.
Each row in the .csv may have none or more emails separated by ",".
f.e.
Email
info#domain.com, email#domain.com, person#contonso.com
something#domain.com
My goal is to write it that way so I can get the "info#" from the row if it is present + 1 extra email from the row if it is present. If there is no "info#" get at least 1 or 2 emails from that row.
Here is the fracture of the code, where I am manually able to say on what position is what email, but I am not able to get this part to work in the for cycle which I could use to enumerate the number of occurences as it appears I cannot convert it to int at all.
$Occurrences = $email.Split(",").GetUpperBound(0);
[int]$Occurrences
$data = Import-Csv -path $path
foreach($contact in $data)
{
$email = $contact.Email
if($email.Contains("info"))
{
$emailSplit = $contact.Email.Split(",")
$Occurrences = $email.Split(",").GetUpperBound(0);
[int]$Occurrences
$name = $domainSplit[0]
for([int]$i = 0;-lt $Occurrences.ToInt32(); $i++)
{
}
}
}
Any help is appreciated.
This is not a valid CSV Format. Cant you export the data via JSON from the datasource?
You need to split the single lines and then do your operations
$data = Get-Content -path $path
for($i=1; $i -lt $data.Length; $i++)
{
$emailSplit = [array]$data[$i].Split(",")
for($j = 0; $j -lt $emailSplit.Length; $j++) {
<#do your operation here...
loop once through the elements, check for info#, and then assign them accoringly...
#>
}
}
V2:
$data = Get-Content -path $path
for($i=1; $i -lt $data.Length; $i++)
{
$emailSplit = [array]$data[$i].Split(",")
Write-Host ('Results for line: ' + $i)
$infoFound = $false
for($j = 0; $j -lt $emailSplit.Length; $j++) {
if($emailSplit[$j] -match 'Info#*') {
$infoFound = $true
$infoPos = $j
}
}
[array]$results = $emailSplit[0]
$results += $emailSplit[-1]
if($infoFound) {
if($infoPos = 0) {$results[1] = $emailSplit[$infoPos]}
else {$results[0] = $emailSplit[$infoPos]}
}
Write-Host ('Element1: ' + $results[0] + ' Element2: ' + $results[1])
}

Powershell sorting array into multi-dimensional array with the “-like” comparison operator

I'am trying to collect my array into a multidimensional array by using the -like comparison operator for further processing.
I wrote the following array loop but i cannot replace "*kw1*" with "*$keyword[$j]*". It will break the operator validation.
$keywords = #("kw1", "kw2")
$list = #("name_kw1_000", "name_kw1_001", "name_kw1_002", "name_kw2_000", "name_kw2_001", "name_kw2_002")
$mdarr= New-Object object[][] $keywords.Length
for ($i = 0; $i -lt $list.Length; ++$i) {
for ($j = 0; $j -lt $keywords.Length; ++$j) {
if ( $list[$i] -like "*kw1*" ) {
$mdarr[$j] += $list[$i];
}
}
}
My expected output is:
$mdarr[0]
name_kw1_000
name_kw1_001
name_kw1_002
$mdarr[1]
name_kw2_000
name_kw2_001
name_kw2_002
Is this possible with the above array loop or would i have to do this completely different since the -like operator does not seem to be array friendly.
I think you mean to get output for a variable length array, using more keywords.
As montonero comments, you never test if the keyword is actually part of the item in the list of words.
Maybe this will help:
# there is no need to enclose the items with '#()'
$keywords = "kw1", "kw2"
$list = "name_kw1_000", "name_kw1_001", "name_kw1_002", "name_kw2_000", "name_kw2_001", "name_kw2_002"
# in case your keywords contain characters that have special meaning
# for regex '-match', we should escape these characters.
$keywords = $keywords | ForEach-Object { [RegEx]::Escape($_) }
# fill the object array
$mdarr= New-Object object[][] $keywords.Count
for ($i = 0; $i -lt $keywords.Count; $i++) {
foreach ($item in $list) {
if ($item -match $keywords[$i]) {
$mdarr[$i] += $item
}
}
}
# write result
for ($i = 0; $i -lt $mdarr.Count; $i++) {
Write-Host ("`$mdarr[$i]") -ForegroundColor Yellow
$mdarr[$i]
}
This will output
$mdarr[0]
name_kw1_000
name_kw1_001
name_kw1_002
$mdarr[1]
name_kw2_000
name_kw2_001
name_kw2_002

Powershell Do Until Loop

$StartID = Read-Host -Prompt "StartID"
$StopID = Read-Host -Prompt "StopID"
$i = $StartID
do {
Write-Host $startID
Write-Host $StopID
$i = ($StartId + 1)
} until ($i -gt $StopID)
The first problem is that after the statement $i = $startid + 1, the $i equals 11 and not 2.
The second problem is that even though the until statement says that it should stop when $i -gt $stop the loop continues forever.
How do I get the $i to increase by 1 and not 10 and how do I stop the loop when $i -gt $stop.
Read-Promptreturns a string per default (this stackoverflow answer explains different ways for conversion). You've to convert/cast the string to a numeric value:
[int]$start = Read-Host -Prompt "Start"
[int]$stop = Read-Host -Prompt "Stop"
do {
Write-host $start
$start++
} until ($start -ge $stop)
Hope that helps.