views:

361

answers:

2

The Rename-Item accepts a scriptblock (I think...) as a parameter so I can do something like this if I want to rename a bunch of files (for example):

Dir *.ps1 | Rename-item -NewName {$_.Name -replace ".ps1" ".txt" }

I'm writing a cmdlet to rename some items and would like to be able to use syntax like this for the new name, but how to declare the parameter to accept a script block like this or a simple string?

A: 

Yes. -NewName takes a script block. Try this:

Function Do-MyRename {
  param([ScriptBlock]$sb)

  dir *.ps1| Rename-Item -NewName $sb
}
Doug Finke
+2  A: 

If you are writing a .NET based cmdlet (C#/VB) then keep in mind that any parameter that is pipeline bound will support scriptblocks automatically. That is just a feature on PowerShell. If however, the parameter you want to use isn't pipeline bound then you can do this:

[Parameter]
public ScriptBlock NewName { get; set; }

[Parameter(ValueFromPipeline = true)]
public string OldName { get; set; }

protected override void ProcessRecord()
{
    Collection<PSObject> results = NewName.Invoke(this.OldName);
    this.Host.UI.WriteLine("New name is " + results[0]);
}

The only thing I don't like about this approach is that you can't use $_ in the scriptblock you have to use $args[0] in this case. Perhaps there is a better way to do this and somebody will chime in with it.

OTOH, Rename-Item does specify the NewName parameter as pipeline bound by property name. In this case, you just make the NewName parameter be the type you want (string) and let PowerShell do the scriptblock magic. Best of all, in this case $_ works in the scriptblock e.g.:

[Parameter(ValueFromPipelineByPropertyName = true)]
public string NewName { get; set; }

[Parameter(ValueFromPipeline = true)]
public string OldName { get; set; }

protected override void ProcessRecord()
{
    this.Host.UI.WriteLine("New name is " + this.NewName);
}
Keith Hill
Yes, that's what I wanted to do - if the Rename-Item sets the parameter as pipeline bound that's good enough for me.
marcus.greasly