Search code examples
powershellrename-item-cmdlet

How to convert the contents of a variable to a string?


I have 5 variables and I have 3 files.

$NumOne = Read-Host 'Enter four digit numone'
$NumTwo = Read-Host = 'Enter two digit numtwo'
$sdataJRN= $NumOne + $NumTwo + "00" + ".jrn"
$sdataJNM = $NumOne + $NumTwo + "00" + ".jnm"
$sdataTXN = $NumOne + $NumTwo + "00" + ".txn"

Right now the three files are 06540200.jnm and jrn and txn respectively.

I want to rename each of these files. Instead of being 00 at the end I want 99. 06540299 jrn jnm txn

I am doing this with the following lines:

Rename-Item $sdataJRN -NewName $NumOne,$NumTwo,"99",".jrn"

Rename-Item $sdataJNM -NewName $NumOne,$NumTwo,"99",".jnm"

Rename-Item $sdataTXN -NewName $NumOne,$NumTwo,"99",".txn"

This returns an error.

Rename-Item : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'NewName'. Specified method is not supported.
At line:1 char:34
+ Rename-Item $sdataJRN[0] -NewName <<<<  $storeNum,$regNum,"99",".jrn"
    + CategoryInfo          : InvalidArgument: (:) [Rename-Item], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.RenameItemCommand

Solution

  • What you're looking for is a delay-bind script block, which allows you to derive a parameter value from each input object:

    Note: As in your code, the assumption is that the input files are located in the current directory.

    $sdataJRN, $sdataJNM, $sdataTXN |
      Rename-Item -NewName { $_ -replace '00\.([^.]+)$', '99.$1' }
    

    { ... } is a delay-bind script block that is evaluated for each input object, and inside of it automatic variable $_ refers to the input object at hand.

    The -replace operator operates on regexes (regular expressions):

    • 00\.([^.]+)$ matches 00 before a literal . (\.), followed by one ore more characters that aren't literal . ([^.]) at the end of the string ($).

    • By enclosing [^.]+ in (...), the match - the filename extension, in this case - is captured so that it can be referenced in the replacement operand as $1, i.e., the 1st (and in this case only) capture group.

    • Replacement operand 99.$1 then replaces everything the regex matched with literal 99., followed by the value of $1, i.e., the value of the 1st capture group, i.e., the input filename extension.


    As for what you tried:

    Rename-Item $sdataJRN -NewName $NumOne,$NumTwo,"99",".jrn"

    $NumOne,$NumTwo,"99",".jrn" is not a string-concatenation operation, it creates a 4-element array, due to use of ,, PowerShell's array-construction operator.

    Since the -NewName operator is [string]-typed - i.e., a single string, trying to pass an array fails.

    For a specific input name you could have used an expandable string to synthesize the -NewName argument:

    Rename-Item $sdataJRN -NewName "${NumOne}${NumTwo}99.jrn"
    

    That said, the delay-bind solution above offers more flexibility.