3

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?

2 Answers 2

4

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);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, that's what I wanted to do - if the Rename-Item sets the parameter as pipeline bound that's good enough for me.
How have I gotten by this long without knowing that you can use ScriptBlocks in this context?? I would assume that this results in less overhead as compared with wrapping in a ForEach command?
@JoshEinstein I would think it is less overhead. One less cmdlet to run begin/process/end on.
"any parameter that is pipeline bound will support scriptblocks automatically" -- This is explained at about_Script_Blocks and more in depth in this answer.
3

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

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

  dir *.ps1| Rename-Item -NewName $sb
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.