locked
PS Get-Content - file containing environement variable RRS feed

  • Question

  • Hello

    I have an issue with a script where I have a text file containing folders and files. I get them with Get-Content and then I copy them somewhere else.

    My problem is that I would like to be able to use environement variable in the text file, like D:\$env:USERNAME\Documents but when I get them through Get-Content, variable are not converted.

    Is there a way to make Powershell recognizing variables in the path ?

    Thanks !

    Tuesday, October 21, 2014 3:34 PM

Answers

  • Try it this way:


    $sourcelist = get-content D:\liste.txt | foreach-object {
      $ExecutionContext.InvokeCommand.ExpandString($_)
    }
    

    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Mike Laughlin Tuesday, October 21, 2014 4:17 PM
    • Marked as answer by Bill_Stewart Wednesday, November 19, 2014 8:43 PM
    Tuesday, October 21, 2014 4:09 PM

All replies

  • Put your path, D:\$env:USERNAME\Documents, in double quotes. This will expand the variable.

    PS C:\> 'D:\$env:USERNAME\Documents'
    D:\$env:USERNAME\Documents
    PS C:\> "D:\$env:USERNAME\Documents"
    D:\tommymaynard\Documents
    Update: Added example

    Tuesday, October 21, 2014 3:37 PM
  • I tried, but it doesn't work, either in source file or in the script. Let's assume I have this :

    $sourceslist = GET-Content D:\liste.txt
    foreach($source in $sourceslist){ 
            Write-Host $source    
    }

    And the file D:\liste.txt contains this :


    C:\helo
    D:\$env:USERNAME\Documents

    it will not translate $env:USERNAME into the current username.


    Tuesday, October 21, 2014 3:44 PM
  • Okay, now I understand what you're after. Try this example.

    $SourceList = Get-Content -Path 'D:\liste.txt'
    
    Foreach ($Source in $SourceList) {
        $Source = Invoke-Expression -Command "`"$Source`""
        Write-Output -Verbose $Source
    }
    This example is based on the syntax found here: http://stackoverflow.com/questions/1667023/powershell-expanding-variables-in-file-contents.
    • Proposed as answer by Mike Laughlin Tuesday, October 21, 2014 4:07 PM
    • Unproposed as answer by Bill_Stewart Wednesday, November 19, 2014 8:43 PM
    Tuesday, October 21, 2014 4:03 PM
  • Try it this way:


    $sourcelist = get-content D:\liste.txt | foreach-object {
      $ExecutionContext.InvokeCommand.ExpandString($_)
    }
    

    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Mike Laughlin Tuesday, October 21, 2014 4:17 PM
    • Marked as answer by Bill_Stewart Wednesday, November 19, 2014 8:43 PM
    Tuesday, October 21, 2014 4:09 PM
  • I wouldn't recommend Invoke-Expression in this case unless you can be sure the file's contents don't contain something "interesting."


    -- Bill Stewart [Bill_Stewart]

    Tuesday, October 21, 2014 4:12 PM
  • PS C:\Users\User> Add-Content C:\liste.txt 'D:\$env:USERNAME\Documents' Add-Content C:\liste.txt 'D:\Documents'

    $SourceList = Get-Content -Path 'C:\liste.txt' Foreach ($Source in $SourceList) { $Expression= "$"+"Path=""$Source""" "Expression is $Expression" Invoke-Expression $Expression "Path is $Path" }

    Output

    Expression is $Path="D:\$env:USERNAME\Documents"
    Path is D:\User\Documents
    Expression is $Path="D:\Documents"
    Path is D:\Documents


    Tuesday, October 21, 2014 4:30 PM
  • Invoke-Expression is not needed in this case. I recommend the $ExecutionContext.InvokeCommand.ExpandString method instead.

    -- Bill Stewart [Bill_Stewart]

    Tuesday, October 21, 2014 5:41 PM
  • Invoke-Expression is not needed in this case. I recommend the $ExecutionContext.InvokeCommand.ExpandString method instead.

    -- Bill Stewart [Bill_Stewart]

    I'm open to suggestions, (even though what I suggested was demonstrated and works).

    I took your advice and tried your suggestion

    PS C:\Users\User> 
    Add-Content C:\liste.txt 'D:\$env:USERNAME\Documents'
    Add-Content C:\liste.txt 'D:\Documents'
    
    $sourcelist = get-content C:\liste.txt | foreach-object {
      $ExecutionContext.InvokeCommand.ExpandString($_)
    }
    

    There is no output? So I tried assigning it to a variable.

    PS C:\Users\User> 
    Add-Content C:\liste.txt 'D:\$env:USERNAME\Documents'
    Add-Content C:\liste.txt 'D:\Documents'
    
    $sourcelist = get-content C:\liste.txt | foreach-object {
      $Path = $ExecutionContext.InvokeCommand.ExpandString($_)
      $Path
    }

    LOL, there is still no output. 

    Tuesday, October 21, 2014 6:01 PM
  • LOL, there is still no output. 

    Works just fine for me:

    PS C:\Scripts\PowerShell Scripts\Misc Testing\10-21-2014> $sourcelist = get-content .\pathList.txt | foreach-object {
      $ExecutionContext.InvokeCommand.ExpandString($_)
    }
    
    $sourcelist
    C:\helo
    D:\laughlinm\Documents


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Tuesday, October 21, 2014 6:05 PM
  • Assigning variables and moving things around is never a solution to just not seeing what is happening.

    This is the same code but with a little tickler to make it clear.

    Add-Content .\liste.txt 'D:\$env:USERNAME\Documents'
    Add-Content .\liste.txt 'D:\Documents'
    
    Get-content .\liste.txt | 
         ForEach-Object{
            $exp=$ExecutionContext.InvokeCommand.ExpandString($_)
            Write-Host $exp -fore green
    }


    ¯\_(ツ)_/¯

    Tuesday, October 21, 2014 6:17 PM
  • My apologies.

    $ExecutionContext.InvokeCommand does not produce output in V2 but does in V4. Odd behavior.

    Invoke-Expression works the same in both V2 and V4

    Tuesday, October 21, 2014 6:28 PM
  • $ExecutionContext.InvokeCommand does not produce output in V2 but does in V4.

    I just tested it in version 2 and it works for me.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, October 21, 2014 6:35 PM
  • It absolutely works in V2.  It does not work in V1 but V1 is no longer supported and should not be used.


    ¯\_(ツ)_/¯

    Tuesday, October 21, 2014 6:43 PM
  • In V1 mode on a system with V3 or later installed it does work but that is because it is really V2 running compatibility.

    CLRVersion                     2.0.50727.8009
    BuildVersion                   6.1.7600.16385
    PSVersion                      2.0
    WSManStackVersion              2.0
    PSCompatibleVersions           {1.0, 2.0}
    SerializationVersion           1.1.0.1
    PSRemotingProtocolVersion      2.1


    ¯\_(ツ)_/¯

    Tuesday, October 21, 2014 6:47 PM
  • I stand corrected, it does work in V2

    $sourcelist = get-content C:\liste.txt | foreach-object {
      $ExecutionContext.InvokeCommand.ExpandString($_)
    }

    I did not output $sourcelist.

    This is the preferable way to go, as the assignment expression does not need to be constructed and/or in the worst case there is something "interesting".

    Thanks for the tip, I will be using it.


    Tuesday, October 21, 2014 6:51 PM
  • $ExecutionContext.InvokeCommand.ExpandString($_)

    Thanks ! This work just fine. I only have one issue with this in the end, if the path contains a $, it will try to interpret it and remove everything after the $

    Do you think there is a way to prevent this ?

    Wednesday, October 22, 2014 7:19 AM
  •  $ExecutionContext.InvokeCommand.ExpandString('\\xxxxxx\yyyyy`$$env:USERNAME$\Documents')

    YOU must escape the dollar sign.


    ¯\_(ツ)_/¯

    Wednesday, October 22, 2014 7:27 AM
  • Thanks. I think the case will never happen and I will make sure it doesn't.
    Wednesday, October 22, 2014 7:29 AM