1

I want to make rm -rf an alias for Remove-Item, since I keep accidentally typing it when using PowerShell.

I had guessed maybe I could do something like this, but that doesn't work.

Set-Alias -name 'rm -rf' -value Remove-Item
henrycarteruk
  • 12,708
  • 2
  • 36
  • 40
Michael
  • 1,075
  • 1
  • 10
  • 24

3 Answers3

6

You could also remove the default alias and then replace it with a custom function.

# remove default alias
if (Test-Path Alias:rm) {
    Remove-Item Alias:rm
}

# custom function for 'rm'
function rm {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)]
        [switch]$rf,

        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Path
    )
    process {
        Remove-Item -Path $Path -Recurse:$rf -Force:$rf
    }
}

Then call it like this:

rm -rf "C:\Temp\dir"

If course, so far this function doesn't have the full functionality of Remove-Item, but you can extend it as you like.

Note: Even though this "solves" your problem in the short-run, you should not revert to these kinds of workarounds. Better get accustomed to the actual PowerShell commands and syntax, or you're bound to run into more problems sooner or later.

marsze
  • 15,079
  • 5
  • 45
  • 61
3

You already have a solution to your problem but as I mentioned, a proxy function could be suitable in this particular scenario. Here's a working example (atleast for PSVersion 5.1).

Adding the following to your $profile should work and you'd be able to run rm -rf "path" to recursively and forcefully remove a directory. Bear in mind that this hasn't been tested extensively but it does take into account wether you specified -rf or not on the command line. It also supports the common parameters such as -Confirm:$true.

if(Test-Path Alias:rm) { Remove-Item Alias:rm }

function rm
{
    [CmdletBinding(DefaultParameterSetName='Path', SupportsShouldProcess=$true, ConfirmImpact='Medium', SupportsTransactions=$true, HelpUri='https://go.microsoft.com/fwlink/?LinkID=113373')]
    param(
        [Parameter(ParameterSetName='Path', Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string[]]
        ${Path},

        [Parameter(ParameterSetName='LiteralPath', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias('PSPath')]
        [string[]]
        ${LiteralPath},

        [string]
        ${Filter},

        [string[]]
        ${Include},

        [string[]]
        ${Exclude},

        [switch]
        ${Recurse},

        [switch]
        ${Force},

        [switch]
        ${rf},

        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [pscredential]
        [System.Management.Automation.CredentialAttribute()]
        ${Credential})


    begin
    {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
            {
                $PSBoundParameters['OutBuffer'] = 1
            }

            if($rf)
            {
                $PSBoundParameters.Remove('rf') | Out-Null
                $PSBoundParameters.Add('Recurse', $true) | Out-Null
                $PSBoundParameters.Add('Force', $true) | Out-Null
            }

            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Remove-Item', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = {& $wrappedCmd @PSBoundParameters }
            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        } catch {
            throw
        }
    }

    process
    {
        try {
            $steppablePipeline.Process($_)
        } catch {
            throw
        }
    }

    end
    {
        try {
            $steppablePipeline.End()
        } catch {
            throw
        }
    }
    <#

    .ForwardHelpTargetName Microsoft.PowerShell.Management\Remove-Item
    .ForwardHelpCategory Cmdlet

    #>
}
notjustme
  • 2,376
  • 2
  • 20
  • 27
  • I've looked a bit into PowerShell proxy functions as I've never used them before. It was a good hint. You should probably include some info on how to create such a function in your answer. I still think it's a bit overkill for the original problem (which basically just comes from being used to other shells), but nonetheless the most sophisticated workaround. Thanks for making me learn about proxy functions! – marsze Nov 05 '18 at 09:55
  • Agreed that it might be overkill but it's a "great fit" using a proxy function for the particular scenario nonetheless. Shay Levy has a pretty [good article on proxy functions](https://blogs.technet.microsoft.com/heyscriptingguy/2011/03/01/proxy-functions-spice-up-your-powershell-core-cmdlets/) over at The Scripting Guy's blog, even if it's a lil bit dated now. – notjustme Nov 05 '18 at 10:01
  • Yea, that's the one I read. I hope there will be some day I can make use of this knowledge. I doubt it though. – marsze Nov 05 '18 at 10:06
2

It will work. Set the alias as below.

Set-Alias -Name 'rm -rf' -Value Remove-Item

For calling it, you can use the call operator (&) operator like this -

& 'rm -rf' \\PathToYourFileWhichYouWantToDelete\FileName.extension
Vivek Kumar Singh
  • 3,223
  • 1
  • 14
  • 27
  • You are correct that this works - however, since the original poster keeps typing `rm -rf` out of habit I fail to see how being forced to use the call operator will help. Also, `& 'rm -rf' \\PathToYourFileWhichYouWantToDelete\FileName.extension` wouldn't actually be the equivalent in *nix in this case. – notjustme Nov 01 '18 at 07:55
  • `Many times you can execute a command by just typing its name, but this will only run if the command is in the environment path. Also if the command (or the path) contains a space then this will fail. Surrounding a command with quotes will make PowerShell treat it as a string, so in addition to quotes, use the & call operator to force PowerShell to treat the string as a command to be executed.` Hence forcing the call operator. – Vivek Kumar Singh Nov 01 '18 at 08:01
  • Technically, this is the correct answer to the question (if it helps OP's original problem or not). – marsze Nov 01 '18 at 08:08
  • 1
    @marsze I'm not arguing with that. I guess one could say the OP asked the wrong question. ;) – notjustme Nov 01 '18 at 08:12