Can a PowerShell function return a parameterized function as one would in JavaScript (see below)?
I would like to make a reusable code block which renames files in a case-sensitive way. This should not be a function but a code block which I can pass to ForEach-Object
:
$Renamer = {
Rename-Item $_ $_.name.replace("a", "A", $false, $null);
}
Get-ChildItem *.txt | ForEach-Object $Renamer
This works fine but now I want a function which returns the same code block but with different parameters.
function MakeRenamer($from, $to) {
# This doesn't work, $from and $to are undefined
return {
Rename-Item $_ $_.name.replace($from, $to, $false, $null);
}
}
$Renamer = MakeRenamer "a" "A"
Get-ChildItem *.txt | ForEach-Object $Renamer
$Renamer = MakeRenamer "b" "B"
Get-ChildItem *.txt | ForEach-Object $Renamer
This fails implying $from
is null/undefined and thus is not being passed through.
function makeRenamer($from, $to) {
return function(file) {
file.name = file.name.replace(from, to);
}
}
let renamerA = makeRenamer("a", "A");
let renamerB = makeRenamer("b", "B");
let myFile = {name:"aaab.txt"};
console.log(myFile.name); // "aaab.txt
renamerA(myFile);
console.log(myFile.name); // "AAAb.txt
renamerB(myFile);
console.log(myFile.name); // "AAAB.txt
PowerShell supports closures, which is what you're implicitly relying on in javascript - but in PowerShell you need to explicitly request it by calling GetNewClosure
:
function New-Renamer {
param (
[string]$From,
[string]$To
)
return {
$_ |Rename-Item -NewName {$_.Name.Replace($from, $to, $false, $null)}
}.GetNewClosure()
}
$renamer = New-Renamer -From a -To A
Get-ChildItem -Filter *.txt |ForEach-Object $renamer