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
Related
I have created a script section in Gitlab-CI.yaml file. The format is given below.
script:
- powershell -File script.ps1 folderpath="$env:${CI_PROJECT_DIR}" CommitID="$env:${CI_COMMIT_SHORT_SHA}"
and these variables are calling in my PowerShell script as follows. The script is given below.
$Files = Get-ChildItem $folderpath
foreach($eachFile in $Files)
{
if($eachFile.Name.Contains("myapp"))
{
Rename-Item -Path $eachFile.FullName -NewName "myapp-$CommitID.zip" -Force
}
}
This script is using for changing the name of a zip file. After execting this through gitlab I am getting error like this.
Variable reference is not valid. ':' was not followed by a valid variable name
character. Consider using ${} to delimit the name.
Is it the right format to pass the GitLab env variable to PowerShell script? Can you please suggest some inputs on this?
Assuming that ${CI_PROJECT_DIR} is the value of GitLab's CI_PROJECT_DIR (environment) variable, you can use it as-is in your command line - no need for the $env: indirection, which (a) requires the name of an environment variable and (b) wouldn't work anyway with PowerShell's -File CLI parameter.
Assuming your target script uses regular PowerShell parameter declarations (e.g., param($FolderPath, $CommitId), case doesn't matter), you must pass the values using
-<param> <value> or -<param>:<value> syntax.
To put it all together:
script:
- powershell -File script.ps1 -FolderPath "${CI_PROJECT_DIR}" -CommitID="${CI_COMMIT_SHORT_SHA}"
The alternative is not to use parameters at all, and instead directly access the environment variables from inside your script, using PowerShell's $env:<var_name> notation:
$Files = Get-ChildItem $env:CI_PROJECT_DIR
foreach($eachFile in $Files)
{
if($eachFile.Name.Contains("myapp"))
{
Rename-Item $eachFile.FullName -NewName "myapp-$env:CI_COMMIT_SHORT_SHA.zip" -Force
}
}
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))
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
I have problem with path. I need to copy all files from directory I add as 1st parameter in Powershell command.
Now I have:
Copy-Item -Path "$args[0]/" -Filter*.*
So it will copy to location I am now (and it's ok, I don't want other location) but it doesn't copy anything. Please help.
Pretty sure the issue is that the 0 element in $args is not expanding in the string creating an invalid path. Wrap the variable in $() to allow it to expand inside a double quoted string. Else you would end up trying to copy the folder C:\TEST[0]/ which obviously is not correct.
Copy-Item -Path "$($args[0])/" -Filter *.* -Recurse
Not yet sure why you have a forward slash in there since Windows pathing uses backslashes.
function Copy-Something(){
test-Path "$($args[0])/"
test-path "$($args[0])"
}
Copy-Something C:\temp
With what little you have provided the output shows that it might be redundant to have the slash there. Would also recommend calling Test-Path on the argument anyway as it might have caught this for you.
True
True
From Question Comment
You are looking for the -Recurse parameter if you also want folder contents.
From Answer Comment
If you want the contents and not the folder you should be able to do something like this:
Copy-Item -Path "$($args[0])\*" -Filter *.* -Recurse
When in doubt, Get-Help Command.
PS C:\> Get-Help Copy-Item -ShowWindow
-------------------------- EXAMPLE 3 --------------------------
This command copies the contents of the C:\Logfiles directory
to the C:\Drawings\Logs directory. It creates the \Logs
subdirectory if it does not already exist.
Windows PowerShell
PS C:\> Copy-Item C:\Logfiles -Destination C:\Drawings\Logs -Recurse
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.