Recursion - Renaming Issue

Just started messing around with powershell today. I think I’m almost there with this script. Its time to ask the smart people for some help. Any input is fantastic.

I have a top level folder with many folders below. The top level has no files, only folders. Each of the child folders has an xml and a jpeg. the jpegs are all 00000001.jpg. Inside the xml file is a field that has the original name of the image. I am trying to grab the filename from inside the xml and rename the jpeg back to its original name.

I do have this working with the following code but it only works if i paste it into every child folder and run from that folder with the 2 accompanying files. I am looking to move it to the parent folder and have the script open each child folder individually, fish the proper filename and rename the jpeg then copy it to the parent folder.

Something with the -Recurse setup?

Thank you in advance.

$path = Get-ChildItem . *.xml -Recurse
Foreach($p in $path)
{
[xml]$xml = Get-Content $p
[string]$NewName = $xml.index.filename

Rename-Item -Path 00000001.jpg -newname "$($NewName)"
Copy-Item $NewName "D:\tmp"

}

Hi, welcome to the forum :wave:

Firstly, when posting code in the forum, please can you use the preformatted text </> button. It really helps us with readability, and copying and pasting your code (we don’t have to faff about replacing curly quote marks to get things working). If you can’t see the </> in your toolbar, you will find it under the gear icon.

How to format code on PowerShell.org

The problem is that the path for the file in your Rename-Item command (and your Copy-Item command) is relative to where the script is running from and never changes. You need to ensure the path is relative to the current XML file that you’re working with.

$path = Get-ChildItem . *.xml -Recurse
Foreach($p in $path)
{
    [xml]$xml = Get-Content $p
    [string]$NewName = $xml.index.filename

    Push-Location -Path $p.DirectoryName
    Rename-Item -Path 00000001.jpg -newname "$($NewName)"
    Copy-Item $NewName "D:\tmp"
    Pop-Location
}

Ok. Thank you Matt. I understand what you’re saying. So its trying to run from c:\test instead of c:\test\sub and adding the .DirectoryName is getting my sub folder in the equation. It feels like its still stuck in the top level folder based on the error below. Again - thank you for any insight.

I’ve copied the above code and get the following:

Get-Content : Cannot find path 'D:\test\index.xml' because it does not exist.
At D:\Test\renv4.ps1:4 char:17
+     [xml]$xml = Get-Content $p
+                 ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (D:\Test\index.xml:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

Rename-Item : Cannot bind argument to parameter 'NewName' because it is an empty string.
At D:\Test\renv4.ps1:8 char:45
+     Rename-Item -Path 00000001.jpg -newname "$($NewName)"
+                                             ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Rename-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Rena
   meItemCommand

Copy-Item : Cannot bind argument to parameter 'Path' because it is an empty string.
At D:\Test\renv4.ps1:9 char:15
+     Copy-Item $NewName "D:\tmp"
+               ~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Copy
   ItemCommand

If I update the XML line to:
[xml]$xml = Get-Content $p.DirectoryName
which makes sense to me given your previous explanation.

I get the error:

Get-Content : Access to the path 'D:\Test\000000e1' is denied.
At D:\Test\renv4.ps1:4 char:17
+     [xml]$xml = Get-Content $p.DirectoryName
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (D:\Test\000000e1:String) [Get-Content], UnauthorizedAccessException
    + FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand

but this seems the right direction to me.

OK, it needs the full name because it can’t find the file after restoring the folder path:

$path = Get-ChildItem . *.xml -Recurse
Foreach($p in $path)
{
    [xml]$xml = Get-Content $p.FullName
    [string]$NewName = $xml.index.filename

    Push-Location -Path $p.DirectoryName
    Rename-Item -Path 00000001.jpg -newname "$($NewName)"
    Copy-Item $NewName "D:\tmp"
    Pop-Location
}

Matt - thank you greatly. Is there any way I can send you a little sumthin’ sumthin’ as a reward?

You already did. :slight_smile:

1 Like