2

From a Power Shell window, I can use the clear or cls as you all know.

But messing around I found that clear(5) or cls(5) works, also clear the screen (any number works, including negative numbers). But if I try something like clear(abc) or clear("abc") it throws error

abc: The term 'abc' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Why it accepts a number, if the number doesn't do anything (is not the number of lines to clear or anything), and why throws error with non-numerical?

Kalil
  • 69
  • 5
  • 3
    `clear("abc")` doesn't throw, `clear(abc)` does throw because it's a syntax error. and `clear-host` can take any parameter because its a non-advanced function – Santiago Squarzon May 11 '22 at 02:55
  • 1
    @SantiagoSquarzon, the order of precedence doesn't make sense to me. This `cls(Write-Host "Testing")` appears to Write-Host first, then cls. But this `Write-Host "testing" (cls)` appears to cls first and then Write-Host. It seems that the (5) and ("abc") in his examples are executing first - I don't get it. The semicolon is left to right, but this seems to be right to left. Do you have any insight as to why? – Darin May 11 '22 at 03:10
  • 1
    @SantiagoSquarzon `clear(abc)` is not syntax error. It runs `clear` with an argument that's the return value of the command `abc`, but since that file doesn't exist it'll report an error – phuclv May 11 '22 at 03:14
  • 1
    @phuclv it is a syntax error if `abc` is not defined as ___a cmdlet, function, script file, or executable program___ which in OP's case, it is – Santiago Squarzon May 11 '22 at 03:17
  • 3
    @Darin, PowerShell executes the code in parentheses first [about_operators](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.2#grouping-operator--) – Daniel May 11 '22 at 03:19
  • 1
    @Darin that is because the grouping operator `(..)` has the highest precedence in the expression. See [about_Operator_Precedence](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operator_precedence?view=powershell-7.2) – Santiago Squarzon May 11 '22 at 03:19
  • @phuclv Following my previous comment, in `clear(abc)`, the cmdlet `Clear-Host` doesn't run at all, because PowerShell attempts to run `abc` first, since it has highest precedence and since it is not defined it reaches a terminating error. – Santiago Squarzon May 11 '22 at 03:25
  • 1
    @SantiagoSquarzon, thank you! I probably need to read through that to see what other surprises are in there. – Darin May 11 '22 at 03:26
  • 1
    @SantiagoSquarzon yes I meant exactly that. It's not a syntax error but a command-not-found error. If you create a abc.exe for example then it'll run normally – phuclv May 11 '22 at 12:47
  • 1
    As an aside: PowerShell functions, cmdlets, scripts, and external programs must be invoked _like shell commands_ - `foo arg1 arg2` - _not_ like C# methods - `foo('arg1', 'arg2')`. If you use `,` to separate arguments, you'll construct an _array_ that a command sees as a _single argument_. See [this answer](https://stackoverflow.com/a/65208621/45375) for more information. – mklement0 May 11 '22 at 13:59

1 Answers1

3

Building on Santiago Squarzon's comment: the Clear-Host command is a function. You can see this by running:

Get-Command Clear-Host -OutVariable cmd
Output
CommandType     Name
-----------     ----
Function        Clear-Host

Since functions are written in PowerShell, you can also view the contents (definition):

$cmd.Definition
Output (Windows PowerShell 5.1)
$RawUI = $Host.UI.RawUI
$RawUI.CursorPosition = @{X=0;Y=0}
$RawUI.SetBufferContents(
    @{Top = -1; Bottom = -1; Right = -1; Left = -1},
    @{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor})
# .Link
# https://go.microsoft.com/fwlink/?LinkID=225747
# .ExternalHelp System.Management.Automation.dll-help.xml
Output (PowerShell 7.1.3, on Linux)
[Console]::Write((
    & (Get-Command -CommandType Application clear | Select-Object -First 1).Definition
))
# .Link
# https://go.microsoft.com/fwlink/?LinkID=2096480
# .ExternalHelp System.Management.Automation.dll-help.xml

You can view about_Functions_Advanced to read more about this, but without [CmdletBinding()], it's not an "advanced" function and so it won't be validating its arguments in the same way.

Instead the function can access its unnamed arguments in $args but as you can see in the definition, it does not.

Get-Help Clear-Host will show you that it is not expecting any parameters:

NAME
    Clear-Host

SYNOPSIS


SYNTAX
    Clear-Host [<CommonParameters>]


DESCRIPTION


RELATED LINKS
    https://go.microsoft.com/fwlink/?LinkID=225747

REMARKS
    To see the examples, type: "get-help Clear-Host -examples".
    For more information, type: "get-help Clear-Host -detailed".
    For technical information, type: "get-help Clear-Host -full".
    For online help, type: "get-help Clear-Host -online"

Even a non-advanced function that names parameters will have them show up in help output:

function Test-Thing($one, $two) {}
Get-Help Test-Thing
Output
NAME
    Test-Thing

SYNTAX
    Test-Thing [[-one] <Object>] [[-two] <Object>]


ALIASES
    None


REMARKS
    None
briantist
  • 45,546
  • 6
  • 82
  • 127
  • 1
    Nicely done; note that the fact that `[]` shows up in the syntax diagrams of _non_-advanced functions should be considered a bug. – mklement0 May 11 '22 at 14:00
  • @mklement0 I find it hard to believe you haven't already opened a bug report for that – briantist May 11 '22 at 14:03
  • 2
    Fair point, Brian - please see [GitHub issue #17312](https://github.com/PowerShell/PowerShell/issues/17312). It comes down to whether the non-advanced function has comment-based help or not. – mklement0 May 11 '22 at 14:14