PowerShell solutions:
PowerShell 7+ solution:
[Linq.Enumerable]::Zip(
[string[]] (Get-ChildItem . -File).FullName,
[string[]] (Get-Content FileNames.txt)
) | Rename-Item -LiteralPath { $_.Item1 } -NewName { $_.Item2 } -WhatIf
Note: The -WhatIf
common parameter in the command above previews the operation. Remove -WhatIf
once you're sure the operation will do what you want.
The above uses .
to target files in the current directory; adapt as needed.
The System.Linq.Enumerable.Zip
method allows convenient enumeration of pairs of collection elements, as 2-element tuples; note that the arguments must be explicitly typed with casts ([string[]]
) in order for PowerShell to resolve the method call correctly; generally, note that PowerShell, as of 7.0, lacks support for .NET extension methods (which requires explicit use of [System.Linq.Enumerable]
here) and comprehensive support for calling generic methods, though there are feature requests on GitHub - see here and here.
These tuples are piped to Rename-Item
, whose parameters are bound via delay-bind script blocks to dynamically access each input tuple's properties.
PowerShell 6- solution:
# Read the array of lines == new file names from FileNames.txt
$names = Get-Content FileNames.txt
# Get as many files as new file names; '.' targets the current directory;
# Adapt as needed.
$files = (Get-ChildItem . -File)[0..($names.Count-1)]
# Perform the renaming.
$i = 0
$files | Rename-Item -NewName { $names[$script:i++] } -WhatIf
Note: The $i
variable is referred to as $script:i
in the delay-bind script block ({ ... }
), because the script block runs in a child scope.
To make this also work in cases where the parent scope isn't also the script scope, use (Get-Variable -Scope 1 i).Value++
instead of $script:i++
.