Search code examples
powershellcopyrenamesequential-number

Rename file based on grand parent and parent directory and sequentially number multiple files


I have a files which are stored in the format

C:\Users\xx\test powershell script\studyID\number\filenamedfolder\example.jpg

The desired output is:

studyID_number_1

#the final digit should be sequentially numbered for each instance of the jpg in 'filenamedfolder'.

I have used code given in previous answers to find, rename and copy files to the root directory.

I am using Windows 10 and Powershell:

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      15063  1478
Get-childitem "C:\Users\xx\test powershell script\*" -include *.jpg -recurse |% {

$nextName = Join-Path -Path 'C:\Users\xx\test powershell script\*' -ChildPath $_.name

while(Test-Path -Path $nextName)
{
   $nextName = Join-Path "C:\Users\xx\test powershell script" ($_.BaseName + "_$num" + $_.Extension)    
   $num+=1   
}

$ParentOjbect =$_.Directory
$Parent =$ParentOjbect.Name
$GrandParent = $ParentOjbect.Parent
$GreatGran = $GrandParent.Parent
$Extension = $_.Extension
$countRef = [ref] 0

Copy-item $_ -Destination (Join-Path "C:\Users\xx\test powershell script" ('{0}_{1}_{2}{3}' -f $GrandParent,$GreatGran,++$countRef.Value,$Extension))
}

I have attempted to use code to sequentially name files but my code is not sequentially naming files when more than one jpg exists in the 'filenamedfolder'. Instead only one jpg is copied and renamed into the root folder.

I have never coded in powershell and I am not sure what I have done wrong. I cannot seem to find an existing answer. Could anyone please suggest an adjustment to get this working?


Solution

  • As you want to renumber per directory I suggest to:

    • first Set-Location to the BaseDir
    • do a Get-ChildItem with multiple wildcards to keep the same subdir depth
    • group by Directory and only renumber inside this group

    This sample tree:

    > tree /F
    ├───studyID1
    │   ├───number1
    │   │   └───filenamedfolder
    │   │           example1.jpg
    │   │           example2.jpg
    │   │
    │   └───number2
    │       └───filenamedfolder
    │               example1.jpg
    │               example2.jpg
    │
    └───studyID2
        ├───number1
        │   └───filenamedfolder
        │           example1.jpg
        │           example2.jpg
        │
        └───number2
            └───filenamedfolder
                    example1.jpg
                    example2.jpg
                    example3.jpg
    

    processed by this script:

    ## Q:\Test\2019\05\21\SO_56236909.ps1
    
    $BaseDir = Join-Path $ENV:USERPROFILE "test powershell script"
    Push-Location $BaseDir
    
    Get-ChildItem -Path *\*\*\* -Filter *.jpg -File |
      Group-Object Directory | ForEach-Object {
        $Cnt=1
        $DirName = $_.Group[0].Directory.Name
        $Number  = $_.Group[0].Directory.Parent.Name
        $StudyID = $_.Group[0].Directory.Parent.Parent.Name
        $_.Group | Rename-Item -NewName {"{0}_{1}_{2}_{3}.jpg" -f `
                      $StudyID,$Number,$DirName,$Script:Cnt++ } -WhatIf
      }
    Pop-Location
    

    If the output looks OK, remove the -WhatIf

    yields this resulting tree:

    > tree /F
    ├───studyID1
    │   ├───number1
    │   │   └───filenamedfolder
    │   │           studyID1_number1_1.jpg
    │   │           studyID1_number1_2.jpg
    │   │
    │   └───number2
    │       └───filenamedfolder
    │               studyID1_number2_1.jpg
    │               studyID1_number2_2.jpg
    │
    └───studyID2
        ├───number1
        │   └───filenamedfolder
        │           studyID2_number1_1.jpg
        │           studyID2_number1_2.jpg
        │
        └───number2
            └───filenamedfolder
                    studyID2_number2_1.jpg
                    studyID2_number2_2.jpg
                    studyID2_number2_3.jpg