What you are doing is almost fine, the error comes from trying to concatenate an int with a string, PowerShell attempts type conversion of all elements to the type of the leftmost object in the operation:
The operation that PowerShell performs is determined by the Microsoft .NET type of the leftmost object in the operation. PowerShell tries to convert all the objects in the operation to the .NET type of the first object. If it succeeds in converting the objects, it performs the operation appropriate to the .NET type of the first object. If it fails to convert any of the objects, the operation fails.
Since the leftmost object in this case (the .Length
property) is of the type int PowerShell attempts to convert the rest to int and it fails, for example:
PS /> 1 + 'A'
InvalidArgument: Cannot convert value "A" to type "System.Int32". Error: "Input string was not in a correct format."
This would be easily fixed by type casting the returned value to sring:
-NewName { [string](Get-Content $_).Length + "_" + $_.BaseName + $_.Extension }
Or for example using string formatting or the -f
format operator:
-NewName { '{0}_{1}{2}' -f (Get-Content $_).Length, $_.BaseName, $_.Extension }
As for "the bonus", with string formatting see How do I control the number of integral digits?
In this case you can use {0:0000}
, as an example:
(0..1000).ForEach({'{0:0000}' -f $_})
On the other hand, if you have many lengthy files, [System.IO.File]::ReadAllLines(...)
is likely to be faster than Get-Content
:
-NewName { '{0:0000}_{1}' -f [System.IO.File]::ReadAllLines($_).Length, $_.Name }
# OR
$io = [System.IO.File]
-NewName { '{0:0000}_{1}' -f $io::ReadAllLines($_).Length, $_.Name }