2

Trying just to write a simple script that would return the SHA256 signature of a file using the file name passed to my ps1 script :

The scriptname is sha256sum.ps1.

The first argument will be any file, example :

sha256sum.ps1 dummy.exe

I tried these inside sha256sum.ps1 :

Get-FileHash -algo SHA256 %1
Get-FileHash -algo SHA256 $1
Get-FileHash -algo SHA256 $args[1]

but none of them worked.

Is there a simple way to do that ?

EDIT : Here is the final version of my script thanks to your help, guys :)

#!/usr/bin/env pwsh
param( $firstArg )

function calcSignature( $filename ) {
    $scriptName = Split-Path -Leaf $PSCommandPath
    switch( $scriptName ) {
        "md5sum.ps1"    { $algo = "MD5";    Break }
        "sha1sum.ps1"   { $algo = "SHA1";   Break }
        "sha256sum.ps1" { $algo = "SHA256"; Break }
        "sha384sum.ps1" { $algo = "SHA384"; Break }
        "sha512sum.ps1" { $algo = "SHA512"; Break }
    }
    (Get-FileHash -algo $algo $filename).Hash + "  " + $filename
}

calcSignature( $firstArg )

Now I only have one script and the others are links pointing to sha256sum.ps1.

SebMa
  • 4,037
  • 29
  • 39

2 Answers2

3

I'm guessing you're looking for "How to pass an argument to your .ps1 script".

This is an example of how the script sha256sum.ps1 would look:

param(
    [parameter(mandatory)]
    [validatescript({
        Test-Path $_ -PathType Leaf
    })]
    [system.io.fileinfo]$File
)

(Get-FileHash $File -Algorithm SHA256).Hash

Now, if we were to call this script, as an example:

PS \> .\sha256sum.ps1 .\test.html
1B24ED8C7929739D296DE3C5D6695CA40D8324FBF2F0E981CF03A8A6ED778C9C

Note: the current directory is where the script and the html file are located, if that was not the case, you should use the absolute path.


I would recommend you to the official docs to get a concept on functions and the param(...) block.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
2

Santiago's helpful answer shows how you to properly declare parameters for your script, which is generally preferable.

As for what you tried:

The automatic $args variable contains arguments not bound to any declared parameters. In other words: if your script doesn't declare any parameters, $args is the only way to access any arguments that were passed.

The first argument is at index 0, not 1.

Note:

  • This differs from other shells / programming language where the element at index 0 reflects the script / program being called.
  • Thus, for instance, %1 in a batch file and $1 in a bash script - both of which contain the first argument - correspond to $args[0] in PowerShell.

Therefore, Get-FileHash -algo SHA256 $args[0] should have worked.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 2
    @SebMa, I thought so. I've updated the answer to address the potential confusion more explicitly. – mklement0 Nov 04 '21 at 21:27
  • 1
    Thanks. Is there another command to get the script name without the path ? – SebMa Nov 04 '21 at 21:32
  • 2
    @SebMa, use `Split-Path -Leaf $PSCommandPath` – mklement0 Nov 04 '21 at 21:35
  • 1
    @SebMa `$MyInvocation.MyCommand.Name` can work too – Santiago Squarzon Nov 04 '21 at 21:44
  • 2
    @Santiago-Squarzon `$MyInvocation.MyCommand.Name` returns the function name when called from inside a function. – SebMa Nov 04 '21 at 21:53
  • 1
    @SebMa that's right, but given that you were calling the script externally and not using a function, it would return the script name in that case. – Santiago Squarzon Nov 04 '21 at 21:59
  • 1
    @SantiagoSquarzon You're right. But I have the habit of re-using my code. So if I don't want to get into trouble later when writing functions. I think I'll stick to the `$PSCommandPath` variable which seems the most reliable since PS3.0 according to [this](https://stackoverflow.com/a/43643346/5649639). – SebMa Nov 04 '21 at 22:10
  • @mklement0 How'bout (`%*` or `$@`) and `argc` ? Is there any equivalent ? Do you have any documentation on their equivalent ? – SebMa Nov 05 '21 at 09:43
  • 1
    @SebMa, `$args` is the array of _all_ unbound arguments, and as such it is the analog of `%*` and `$@`. The answer already links to the documentation for `$args`. If by `argc` you mean the _count_ of arguments, simply use `$args.Count`. – mklement0 Nov 05 '21 at 13:56
  • @mklement0 In the meantime I found `$args.Length`, is this the same as `$args.Count` ? – SebMa Nov 05 '21 at 19:40
  • 1
    @SebMa. Yes, they're the same. `.Length` is the type-native property. `.Count` is provided via the `ICollection` interface. `.Count` is preferable for consistency, because most collection types have only a `.Count` property. – mklement0 Nov 05 '21 at 20:19