Powershell pitfalls

后端 未结 21 1193
梦谈多话
梦谈多话 2020-12-23 01:44

What Powershell pitfalls you have fall into? :-)

Mine are:

# -----------------------------------
function foo()
{
    @(\"text\")
}

# Expected 1, a         


        
相关标签:
21条回答
  • 2020-12-23 02:27

    Mine are both related to file copying...

    Square Brackets in File Names
    I once had to move a very large/complicated folder structure using Move-Item -Path C:\Source -Destination C:\Dest. At the end of the process there were still a number of files in source directory. I noticed that every remaining file had square brackets in the name.

    The problem was that the -Path parameter treats square brackets as wildcards.
    EG. If you wanted to copy Log001 to Log200, you could use square brackets as follows: Move-Item -Path C:\Source\Log[001-200].log.

    In my case, to avoid square brackets being interpreted as wildcards, I should have used the -LiteralPath parameter.

    ErrorActionPreference
    The $ErrorActionPreference variable is ignored when using Move-Item and Copy-Item with the -Verbose parameter.

    0 讨论(0)
  • 2020-12-23 02:28

    Forgetting that $_ gets overwritten in blocks made me scratch my head in confusion a couple times, and similarly for multiple reg-ex matches and the $matches array. >.<

    0 讨论(0)
  • 2020-12-23 02:29
    # The pipeline doesn't enumerate hashtables.
    $ht = @{"foo" = 1; "bar" = 2}
    $ht | measure
    
    # Workaround: call GetEnumerator
    $ht.GetEnumerator() | measure
    
    0 讨论(0)
  • 2020-12-23 02:29

    There are some tricks to building command lines for utilities that were not built with Powershell in mind:

    • To run an executable who's name starts with a number, preface it with an Ampersand (&).

    & 7zip.exe

    • To run an executable with a space anywhere in the path, preface it with an Ampersand (&) and wrap it in quotes, as you would any string. This means that strings in a variable can be executed as well.

    # Executing a string with a space. & 'c:\path with spaces\command with spaces.exe'

    # Executing a string with a space, after first saving it in a variable. $a = 'c:\path with spaces\command with spaces.exe' & $a

    • Parameters and arguments are passed to legacy utilities positionally. So it is important to quote them the way the utility expects to see them. In general, one would quote when it contains spaces or does not start with a letter, number or dash (-).

    C:\Path\utility.exe '/parameter1' 'Value #1' 1234567890

    • Variables can be used to pass string values containing spaces or special characters.

    $b = 'string with spaces and special characters (-/&)' utility.exe $b

    • Alternatively array expansion can be used to pass values as well.

    $c = @('Value #1', $Value2) utility.exe $c

    • If you want Powershell to wait for an application to complete, you have to consume the output, either by piping the output to something or using Start-Process.

    # Saving output as a string to a variable. $output = ping.exe example.com | Out-String

    # Piping the output. ping stackoverflow.com | where { $_ -match '^reply' }

    # Using Start-Process affords the most control. Start-Process -Wait SomeExecutable.com

    • Because of the way they display their output, some command line utilities will appear to hang when ran inside of Powershell_ISE.exe, particularly when awaiting input from the user. These utilities will usually work fine when ran within Powershell.exe console.
    0 讨论(0)
  • 2020-12-23 02:29

    Functions 'foo' and 'bar' looks equivalent.

    function foo() { $null  }
    function bar() { }
    

    E.g.

    (foo) -eq $null
    # True
    
    (bar) -eq $null
    # True
    

    But:

    foo | %{ "foo" }
    # Prints: foo
    
    bar | %{ "bar" }
    # PRINTS NOTHING
    

    Returning $null and returning nothing is not equivalent dealing with pipes.


    This one is inspired by Keith Hill example...

    function bar() {}
    
    $list = @(foo)
    $list.length
    # Prints: 0
    
    # Now let's try the same but with a temporal variable.
    $tmp = foo
    $list = @($tmp)
    $list.length
    # Prints: 1
    
    0 讨论(0)
  • 2020-12-23 02:31

    Another fun one. Not handling an expression by default writes it to the pipeline. Really annoying when you don't realize a particular function returns a value.

    function example() {
      param ( $p1 ) {
      if ( $p1 ) {
        42
      }
      "done"
    }
    
    PS> example $true 
    42
    "done"
    
    0 讨论(0)
提交回复
热议问题