How to supply argument to value of New-Alias command? - powershell

I wish Get-ChildItem -force to get executed when I type ll and I have this in my profile.ps1:
New-Alias -Name ll -Value Get-ChildItem -force
However, when I type ll, I can see that the -force argument is not being used. What am I doing wrong?
Edit: What I really wish to achieve is to show all files in a folder, even if they're hidden. And I wish to bind this to ll.

You cannot do that with aliases. Aliases are really just different names for commands, they cannot include arguments.
What you can do, however, is, write a function instead of using an alias:
function ll {
Get-ChildItem -Force #args
}
You won't get tab completion for arguments in that case, though, as the function doesn't advertise any parameters (even though all parameters of Get-ChildItem get passed through and work). You can solve that by effectively replicating all parameters of Get-ChildItem for the function, akin to how PowerShell's own help function is written (you can examine its source code via Get-Content Function:help).

To add to Joey's excellent answer, this is how you can generate a proxy command for Get-ChildItem (excluding provider-specific parameters):
# Gather CommandInfo object
$CommandInfo = Get-Command Get-ChildItem
# Generate metadata
$CommandMetadata = New-Object System.Management.Automation.CommandMetadata $CommandInfo
# Generate cmdlet binding attribute and param block
$CmdletBinding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($CommandMetadata)
$ParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBloc($CommandMetadata)
# Register your function
$function:ll = [scriptblock]::Create(#'
{0}
param(
{1}
)
$PSBoundParameters['Force'] = $true
Get-ChildItem #PSBoundParameters
'#-f($CmdletBinding,$ParamBlock))

Related

Need PowerShell alias for cargo commands [duplicate]

I want to create an alias in Windows PowerShell to delete multiple folders from the command line.
To remove more than one item I call:
Remove-Item '.\Documents\*\Bin\' ,'.\Documents\*\Inter\' -Force -Recurse
I have tried to create the alias like this:
New-Alias -Name 'Clean-RCD' Remove-Item '.\Documents\*\Bin\' ,'.\Documents\*\Inter\' -Force -Recurse
Output:
New-Alias: A positional parameter cannot be found that accepts argument 'System.Object[]'.
Any idea how to define this alias correctly?
Unlike in bash, aliases in PowerShell are strict 1-to-1 command name mappings - no extra parameter arguments allowed.
You'll want to create a function instead:
function Clean-RCD {
Remove-Item -Path '~\Documents\*\Bin', '~\Documents\*\Inter\' -Force -Recurse
}
Use of ~ (which resolves to your home folder) over . is intentional - this way it'll still work if you've navigated to a different path

How can I pass a result of a program as an argument to cmdlet?

Let say there are two separate commands that work well:
$x = where.exe cmd.exe
Get-Item -Path $x
How can I write the above in one line only, without using variable x ?
I tried the below, but it didn't work
Get-Item -Path {where.exe cmd.exe}
Get-Item -Path $(where.exe cmd.exe)

A function "alias" that needs to pass along parameters

I have put the following into my $PROFILE:
function dir
{
Get-ChildItem -Force $args
}
What I want is a simple "dir" command that lists all files, including hidden and system files.
However, as soon as I pass some parameters along:
dir \ -Directory
I am rewarded with a full listing of my root followed by this error:
Get-ChildItem : Cannot find path 'C:\Users\myuser-Directory' because
it does not exist.
My intention was of course that my little homebrewed "alias" would expand into this:
Get-ChildItem -Force \ -Directory
But instead "-Directory" gets treated as a string literal. How can I make my dir function pass arguments the way I intended (rather than as an array of string)?
$args is an array. If you use it like this:
Get-ChildItem -Force $args
it's the same as if you did this:
Get-ChildItem -Force -Path '\', '-Directory'
which works (in a way), because the parameter -Path accepts array input.
Use splatting to avoid this pitfall:
Get-ChildItem -Force #args

Setting an alias with attributes in PowerShell

I wanted to set an alias for listing files in the directory, but Set-Alias -name lf -value ls -file does not seem to work. I intend to use this the Unix alias way.
An alias can't do that. From the help for Set-Alias:
You can create an alias for a cmdlet, but you cannot create an alias for a command that consists of a cmdlet and its parameters.
However, using a technique called "splatting", a function can do it easily:
function lf {
ls -file #args
}
For more information, see help about_splatting.
Example 5 from Get-Help Set-Alias -Full is what you want:
Function lsfile {Get-Childitem -file}
Set-Alias lf lsfile
Append to the answer from #mike-z .
You can put the function definition into the PowerShell profile so that you can reuse it opening shell again.
test-path $profile
// Ensure it doesn't exists before creating the profile!
new-item -path $profile -itemtype file -force
notepad $profile
Simply put the code into the file:
function lf { ls -file #args }
You can check the details from official documentation.

'Get-ChildItem -Include/-Exclude' in PowerShell doesn't filter if passed as an argument to a function

I have a problem getting a filter argument to Get-ChildItem in a function.
The following works fine and displays a whole list of files:
c:\temp\Get-ChildItem -Include *deleteme*.txt -Recurse
Now say I have the following script
#file starts here
#filename = GetLastFile.ps1
param([string] $filter)
$files = Get-ChildItem $filter
Write-Host $files #should print all matching files but prints nothing
$file = $files | Select-Object -Last 1;
$file.name #returns filename
#File ends here
Now trying to run the script,
c:\temp.\GetLastFile.ps1 "-Include *deleteme*.txt -Recurse"
returns nothing.
Supplying a filter, *.*, works fine. It seems to be failing due to the -Include or -Exclude. Any ideas?
You're starting to get into an area where where Powershell 2.0 proxy functions can help. However, short of that, here's a simple way in PowerShell 2.0 to do this assuming all you need is -Include and -Recurse. Actually, I would recommend using -Filter instead it will do what you want and frankly it's quite a bit faster (4x on some of my tests) because -filter uses filesystem filtering provided by the OS whereas -include is processed by PowerShell.
param([string]$Filter, [switch]$Recurse)
$files = Get-ChildItem #PSBoundParameters
Write-Host $files #should print all matching files but prints nothing
$file = $files | Select-Object -Last 1;
$file.name #returns filename
The # symbol is used to "splat" an array or hashtable across the parameters to a command. The $PSBoundParameters variable is an automatic variable new to PowerShell 2.0 that is defined in functions. It's a hashtable that contains all the bounded (named and positional) parameters e.g.:
PS> function foo($Name,$LName,[switch]$Recurse) { $PSBoundParameters }
PS> foo -Name Keith Hill -Recurse
Key Value
--- -----
Name Keith
Recurse True
LName Hill
When you splat a hashtable like this against a command, PowerShell will map the key's (e.g. Recurse) value to the parameter named Recurse on the command.
I believe what is happening is your $filter parameter is being treated as a single string argument to the Get-ChildItem command. As such, unless you have a directory named "-Include deleteme.txt -Recurse", the command will always return nothing.
As for fixing your problem, well, there are a bunch of ways you could approach it. Probably one of the more versatile ways is to switch program behavior if the the $filter argument is passed, and instead of passing the entire filter string just pass the "deleteme.txt" string.
You can use Invoke-Expression to execute a command stored in a variable. For example:
param([string] $filter)
$files = Invoke-Expression "Get-ChildItem $filter"
Write-Host $files
$file = $files | Select-Object -Last 1
$file.name