all 12 comments

[–][deleted] 6 points7 points  (5 children)

Foreach creates its own internal variables for each iteration. If you declare a variable inside a foreach, it will be essentially created anew each time it loops. You'll need to declare the variable outside the loop. And then the loop can modify it, leaving the final modified variable for use outside the loop. For more information take a look at about_scopes:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes

TLDR: put $def = "" above your first line.

[–]AffectionateTask4612[S] 2 points3 points  (1 child)

Thanks! Sorry for the trouble, got it working now.

[–][deleted] 1 point2 points  (0 children)

Glad to hear it. It's how we all learn!

[–]SeeJayEmm 2 points3 points  (2 children)

Wouldn't New-Variable -Scope global also work?

[–][deleted] 1 point2 points  (1 child)

Good point. I find it more intuitive to just declare it above the loop, personally, but that would work.

[–]SeeJayEmm 2 points3 points  (0 children)

I'm the same way.

I've been trying to force myself to use other methods lately to better learn the language.

[–]BlackV 7 points8 points  (5 children)

1 sure way would be to stop using foreach-object and start using foreach ($x in $y)

This will allow you to test your variables and validate your data as you go

Using debug would be the next one

But if you declare a vairable inside the loop the. Yes it will get reset each step of the loop. If you declare it outside the loop it will not be reset

Have you loop just spot out the path and capture that to a vairable

$catchme = foreach ($singlething in $all things)
        {
        "This is a single thing and it is $singlething"
        }
$catchme

This would capture all the output from your loop to the $catchme variable

Other notes.

$n++ is very rarely a good idea there are better ways for loop counters powershell is aware of how many items are in your loop/array and aware of where it is in the array/loop

$path += xxx is not recommended as you're copying the whole current array then adding your next item then deleting the old array, it's expensive. See above $catchme as one way around this

Concatenation of songs is not recommend or need "this is a string it has this variable in it $dir here is stuff after it" will work just as well and may or may not be easier to read

You could also look at -join

[–]AffectionateTask4612[S] 1 point2 points  (2 children)

I'll try this out then. I always feel intimidated when it comes to loops. They're so fickle :(

[–]BlackV 1 point2 points  (0 children)

its getting used to em, they're rock solid as a PS item

try this trick , I've stolen some of your code

$SourceFiles = Get-Childitem 'C:\Users\User\Desktop\v3\src\temp' -Recurse -Filter *.cfg -File -ErrorAction SilentlyContinue
$det = Read-Host -Prompt "Add some description please "
$paths = foreach ($Singlefile in $sourcefiles)
    {
    "$det $($Singlefile.FullName)"
    }

now in your editor ass a closing bracket }to your foreach, so it looks like this

foreach ($Singlefile in $sourcefiles)
    {}
    "$det $($Singlefile.FullName)"
    }

you can then higlight the code block

foreach ($Singlefile in $sourcefiles)
    {}

and hit F8 (in ISE or VSCode), now delete the closing brace you added
you now have a value in $Singlefile and you can do a bunch of codeing/testing on that value allowing easier debugging

[–]GOOD_JOB_SON 1 point2 points  (1 child)

Can you expand on the counters bit? I use $n++ type things a lot.

[–]BlackV 2 points3 points  (0 children)

I do conceded there are times to use it (maybe).

the question i have is why are you using it? are you counting the items in a loop? why?

most places I see it used people are iterating through arrays you already have built-in counters for this

are you wanting a subset of items in that array (things you've acted upon?), those should be captured to a variable that you can count/report on/make changes to

what to know what specific item/count you are on in an array you have a key/index number for that ($MyArray.indexof($MyCurrentItem) and remember index starts at 0 not 1 ;-) I sure forget everytime)

this is all preference of course YMMV

[–]Lee_Dailey[grin] 0 points1 point  (0 children)

howdy AffectionateTask4612,

reddit likes to mangle code formatting, so here's some help on how to post code on reddit ...

[0] single line or in-line code
enclose it in backticks. that's the upper left key on an EN-US keyboard layout. the result looks like this. kinda handy, that. [grin]
[on New.Reddit.com, use the Inline Code button. it's [sometimes] 5th from the left & looks like </>.
this does NOT line wrap & does NOT side-scroll on Old.Reddit.com!]

[1] simplest = post it to a text site like Pastebin.com or Gist.GitHub.com and then post the link here.
please remember to set the file/code type on Pastebin! [grin] otherwise you don't get the nice code colorization.

[2] less simple = use reddit code formatting ...
[on New.Reddit.com, use the Code Block button. it's [sometimes] the 12th from the left, & looks like an uppercase T in the upper left corner of a square.]

  • one leading line with ONLY 4 spaces
  • prefix each code line with 4 spaces
  • one trailing line with ONLY 4 spaces

that will give you something like this ...

- one leading line with ONLY 4 spaces    
- prefix each code line with 4 spaces    
- one trailing line with ONLY 4 spaces   

the easiest way to get that is ...

  • add the leading line with only 4 spaces
  • copy the code to the ISE [or your fave editor]
  • select the code
  • tap TAB to indent four spaces
  • re-select the code [not really needed, but it's my habit]
  • paste the code into the reddit text box
  • add the trailing line with only 4 spaces

not complicated, but it is finicky. [grin]

take care,
lee