1

I would like to create a powershell function or cmdlet that would allow me to quickly navigate to files and function like the example below. Could someone enlighten me to what the "/D" would be called? Is it a parameter?

C:\Windows\system32> folder /help
Usage: Select directory folder [/? | /Username | /S | /D] 

No args    Display help. This is the same as typing /?.
/?         Display help. This is the same as not typing any options.
/Username  Change to the "Username" directory
/S         Change to the "scripts" directory
/D         Change to the "desktop" directory

C:\Windows\system32> folder /username
C:\Users\username> folder /S
C:\Users\username\desktop\scripts> folder /D
C:\Users\username\desktop>

This is what I have so far. This will only take me to the desktop directory, how would I write this to have it named "folder" and add the modifier/parameters?

function desktop { cd "C:\users\username\desktop" }

This functions as following:

C:\Windows\system32> desktop
C:\Users\username\desktop>
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • This is unclear. Can you tell us what you want to type into the prompt and what you expect to happen? The way this reads it seems you want to type `banana` into the prompt and be moved to a folder called `banana` . – another victim of the mouse Apr 27 '22 at 20:44
  • A cmdlet would be a little more difficult given that it's compiled and written in a .Net language. Anyways, this frankly isn't too hard to do as long as you specify/hard-code the paths you'd want to switch in-between. To answer your question though, yes, `/d` is a parameter but, so are the others. We can refer to them as *switches*, or *flags* since they are binary and are either there, or not. Building a function with switches like `folder.exe` is totally doable and I suggest looking into the `$env:` drive where you will find variables like `$env:userprofile` :) – Abraham Zinala Apr 27 '22 at 20:50
  • @anothervictimofthemouse no, that's what the existing code does. Read the above script "help" and pseudo code. Folder would be the command the /D for desktop would be the parameter – user14894283 Apr 29 '22 at 15:40

2 Answers2

4

Yes, in PowerShell lingo /D is called a parameter (other shells may call it an option or a flag, as Abraham Zinala notes), but note that PowerShell only accepts - as the parameter-name sigil, so it would have to be -D (on invocation you're free to use -d or -D, because parameter names aren't case-sensitive in PowerShell).
A parameter that acts as an on/off switch (called a flag in other shells, i.e. one that doesn't take an argument), is called a switch [parameter] in PowerShell.

Note that while you can define single-letter parameter names in PowerShell, it is customary to use longer, descriptive names, e.g. -Desktop:

  • Thanks to what PowerShell calls elastic syntax, you can still use just -d on invocation, as long as the d unambiguously implies the full target parameter name (e.g., -Desktop).

  • Alternatively, you may explicitly declare -d to be an alias for -Desktop, by decorating the parameter declaration with an [Alias()] attribute.

Here's a sample function that works slightly differently from what you specified, but operates in a more PowerShell-idiomatic way:

  • Parameter-less invocation changes to the current user's home folder.

    • To target a different user's home folder, pass the username to the -u / -UserName parameter.
  • Whatever user's home folder is chosen in a given invocation can optionally be combined with either -Desktop / -d or -Scripts / -s, in order to change to the desktop / scripts folder for the targeted user.

  • To show help, use -? (or Get-Help folder), which PowerShell supports by default, showing the command's syntax.

    • To add a verbal description to the help, you can use comment-based help to your function - see the conceptual about_Comment_Based_Help help topic.
  • Push-Location rather than Set-Location (whose built-in alias is cd) is used to change location, to enable returning to the previous folder with Pop-Location (whose built-in aliases are popd and popl)

  • The function below is a so-called advanced function, which means that it acts like a (binary) cmdlet; for more information, see the conceptual about_Functions_Advanced and about_Functions_Advanced_parameters help topics.

function folder {
  [CmdletBinding(DefaultParameterSetName='Default')]
  param(    
    [Alias('u')]
    [string] $Username
    ,
    [Alias('s')]
    [Parameter(ParameterSetName='Scripts')]
    [switch] $Scripts
    ,
    [Parameter(ParameterSetName='Desktop')]
    [Alias('d')]
    [switch] $Desktop
  )

  $targetFolder = 
    if ($Username) { 
      Join-Path (Split-Path -LiteralPath $HOME) $Username
    } else {
      $HOME
    }

  if ($Scripts) {
    $targetFolder += '\Desktop\Scripts'
  } elseif ($Desktop) {
    $targetFolder += '\Desktop'
  }

  Push-Location -LiteralPath $targetFolder
}

Sample calls:

folder             # change to current user's home folder

folder -d          # change to current user's desktop folder

folder -u jdoe -s  # change to jdoe's scripts folder

folder -?          # show help
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank you so much for posting this. Please see my edit, there is something I am missing – user14894283 Apr 29 '22 at 20:55
  • I cannot figure out why it is ignoring my if statement – user14894283 Apr 29 '22 at 21:13
  • it's not the syntax, it ignores the first if statement regardless of which one. – user14894283 Apr 29 '22 at 21:37
  • @user14894283, the first `if` statement is part of the assignment to `$targetFolder` - it is unrelated to the `if` / `elseif` statement that follows. If you want to take action on when _no_ argument is passed, use `if ($PSBoundParameters.Count -eq 0) { ...; return }` as the first statement. – mklement0 Apr 30 '22 at 02:14
  • @user14894283 Thanks! That worked. Could you please explain what you did? What does if ($PSBoundParameters.Count -eq 0) { ...; return } mean and how does it work – user14894283 Apr 30 '22 at 02:31
  • It uses the [automatic `$PSBoundParameters` variable](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Automatic_Variables#psboundparameters) to check the count of explicitly passed arguments. `return` is needed to exit the function right then, to prevent execution of subsequent statements. – mklement0 Apr 30 '22 at 02:34
  • see edit for final error – user14894283 Apr 30 '22 at 02:41
  • @user14894283, a non-`[switch]` (non-Boolean) parameter in PowerShell _requires_ an argument - always. You can work around that for a _single_ parameter, but it is suboptimal - see [this answer](https://stackoverflow.com/q/58838941/45375). – mklement0 Apr 30 '22 at 02:43
0

FINALLY FIXED IT!

I needed a flag or a tracking variable, essentially defining $targetFolder before the first if statement. I wonder if it was tryin to define the target folder as the entire if statement. See the windows documentation for multiple if statements here

function  display-path {Get-ChildItem Env:Path }

    <# 
    **One of these can be used to navigate to the username directory. The first will only allow you to navigate to one user, the second allows for you to select the user.**
    $targetFolder = 
      if ($Username) { 
        $targetFolder += '\user\Username' #replace with your username
      } 
       
    if ($Username) { 
      Join-Path (Split-Path -LiteralPath $HOME) $Username
    } else {
      $HOME
    } #>
    function folder {
        [CmdletBinding(DefaultParameterSetName='Default')]
        param(    
          [Alias('u')]
          [switch] $Username
          ,
          [Alias('s')]
          [Parameter(ParameterSetName='Scripts')]
          [switch] $Scripts
          ,
          [Parameter(ParameterSetName='Desktop')]
          [Alias('d')]
          [switch] $Desktop
          ,
          [Alias('h')]
          [Parameter(ParameterSetName = 'help')]
          [switch]$Help
          ,
          [Alias('r')]
          [Parameter(ParameterSetName = 'root')]
          [switch]$root
        )
      
        $targetFolder =  $env:USERPROFILE
        if ($Username) { 
            $targetFolder = $env:USERPROFILE
            $u = ' -U'
          }
          elseif ($Scripts) {
          $targetFolder += '\Desktop\Scripts'
        }
          elseif ($Desktop) {
          $targetFolder += '\Desktop'
        }
          elseif ($root) {
  
            ## same as other but we can use $env:homedrive for the root of C:
        
            $targetFolder = $env:HOMEDRIVE + '\'
            $r = ' -R '
        
          }
        elseif ($Help) {
        echo "
        -H         Display help. This is the same as not typing any options.
        -U         Change to the 'Username' directory
        -S         Change to the 'scripts' directory
        -D         Change to the 'desktop' directory"
    }
        else {
        echo "
        -H         Display help. This is the same as not typing any options.
        -U         Change to the 'Username' directory
        -S         Change to the 'scripts' directory
        -D         Change to the 'desktop' directory"
    }
      
        Push-Location -LiteralPath $targetFolder
      }

Feel free to use this for your own navigation, thanks for the help! Here's a github link to the code: https://github.com/semiexperienced/Windows-Powershell-Alias-and-Navigation