Question

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?

Was it helpful?

Solution

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);
}

OTHER TIPS

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

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

  dir *.ps1| Rename-Item -NewName $sb
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top