1

Script is working almost how it is intended, still struggling with renaming duplicate files. I cannot figure out how to get it to name the files like

filename(1).ext

filename(2).ext

the closest I have gotten was

filename(1).ext

filename(1)(2).ext

 #region actual script
 $srcRoot = "C:\srcLocation"
 $dstRoot = "C:\dstLocation"

 $fileList = Get-ChildItem -Path $srcRoot -File -Force -Recurse

    foreach ($file in $fileList) {


    $fileName = $file.Name.ToUpper()
    $fileExt = $file.Extension.ToUpper()
     $dstFileName = $null

     switch -Regex ($fileName)
    {
   '[A-Z]{4}-[0-9]{3}' { $dstFileName = $fileName }
   '[A-Z]{4} [0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})\s([0-
    9]{3})','$1-$2' }
   '[A-Z]{4}[0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})([0-9]
    {3})','$1-$2'}
   Default { Write-Warning -Message "$fileName is not an expected filename" 
   }
   }

   if ($dstFileName) {
   $dstDir = $dstFileName.Split('.')[0].Substring(0,8)
   $dstPath = Join-Path -Path $dstRoot -ChildPath $dstDir

   if (-not (Test-Path -Path $dstPath)) {
       New-Item -Path $dstPath -ItemType Directory
   }
   $i = 1
   if (test-path $dstPath\$dstFileName){
           $dstFileName = $dstFileName.Split('.')[0] + "($i)" + $fileExt

   While (test-path $dstPath\$dstFileName){
        $i +=1
        $dstFileName = $dstFileName -replace 

   }
   }


   Write-Verbose "Moving $($file.FullName)"
   Move-Item -Path $($file.FullName) -Destination $dstPath\$dstFileName -
   ErrorAction Continue
   }
   }
   #endregion
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Jimmy
  • 13
  • 1
  • 6
  • You are aware of the fact that naming the path and variables crossed is irritating? I think the mapping isn't necessary, better use a regex matching the structure `'^([A-Z]{4})[- ]([0-9]{3})(.*)$'` –  Aug 15 '17 at 16:22
  • There's nothing about globs in here. Please change the title so you reduce false hits from Google @Jimmy, unless this is intentional click-bait – zumalifeguard Feb 27 '21 at 22:57

2 Answers2

1

You can simply use the Replace method of string objects in PowerShell. To verify your input, you can use a RegEx. Move-Item will throw an error, if the file already exists in the destination anyways. The complete script would look like this.

#region setup
New-Item -Path C:\srcpath,C:\dstpath -ItemType Directory
Set-Location C:\srcpath
New-Item 'ABCD123.txt','ABCD 123.txt','AbCD-123.txt','AAAA111.txt','BBBB 222.jpg','BBBB-222.txt' -ItemType File
#endregion

#region actual script
$srcRoot = "C:\srcpath"
$dstRoot = "C:\dstpath"

$fileList = Get-ChildItem -Path $srcRoot -File -Force -Recurse

foreach ($file in $fileList) {

    $fileName = $file.Name.ToUpper()
    $dstFileName = $null

    switch -Regex ($fileName)
    {
        '[A-Z]{4}-[0-9]{3}' { $dstFileName = $fileName }
        '[A-Z]{4} [0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})\s([0-9]{3})','$1-$2' }
        '[A-Z]{4}[0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})([0-9]{3})','$1-$2'}
        Default { Write-Warning -Message "$fileName is not an expected filename" }
    }

    if ($dstFileName) {
        $dstDir = $dstFileName.Split('.')[0]
        $dstPath = Join-Path -Path $dstRoot -ChildPath $dstDir

        if (-not (Test-Path -Path $dstPath)) {
            New-Item -Path $dstPath -ItemType Directory
        }

        Write-Verbose "Moving $($file.FullName)"
        Move-Item -Path $($file.FullName) -Destination $dstPath\$dstFileName -ErrorAction Continue
    }
}
#endregion

#region result
Write-Host '----- Result -----' -BackgroundColor DarkYellow
Get-ChildItem C:\dstpath -Recurse | Select-Object -ExpandProperty FullName
#endregion
vrdse
  • 2,899
  • 10
  • 20
  • Thank you vrdse! This works like a charm. However, it also sorts by file extension. Which is useful for another project I have going but not so much for this one. I'm thinking I can use .basename to fix this. Thoughts? – Jimmy Aug 16 '17 at 03:01
  • Am I on the right track with `.BaseName`? Also I noticed the `.replace` Isn't working entirely as expected since the directories are all named with the AAA-123 format but the files do not get renamed. – Jimmy Aug 16 '17 at 03:50
  • What do you mean by sort by file extension? – vrdse Aug 16 '17 at 18:37
  • I updated the code. The `Move-Item` contained a wrong variable in the destination. Also my code now takes care of extensions and creates folders without the extension. – vrdse Aug 16 '17 at 18:49
  • the updated code was not working properly, however, I was able to modify it and I believe it now works exactly as I want to. I had a few test files disappear when I was tinkering with the script. While I think it is safe i'm slightly hesitant to run it on important files. I've updated the original post with the new code. – Jimmy Aug 17 '17 at 07:00
  • It was creating directories with the file extension. So it was effectively sorting the files by the extension. I realized there was a file format I forgot to account for `ABCD123` I tried adding this `'[A-Z]{4}[0-9]{3}' {$dstFileName = ([Regex]$insertPoint).Replace($fileName,$insertPoint + '-',1)}` where `$insertPoint = $file.name.substring(3,4)` However it gives an error saying directory cannot be found. Thoughts? – Jimmy Aug 17 '17 at 08:24
  • I updated my script regarding your new requirements and added my "PoC environment" as code. For result output see [Pastebin](https://pastebin.com/Fga5nPLd). – vrdse Aug 18 '17 at 17:00
0
  1. Gets the Files in Source folder (Get-ChildItems)
  2. Renames The File to include a - instead of a " " (Rename-Item)
  3. Sets the Child Name property to the new name ($File.Name)
  4. Creates new Folder in source based on first 4 Chars
  5. Moves-Item to new created folder (move-item)
$Source = "C:\Start"
$Destination = "C:\End"

foreach($File in (Get-ChildItem -Path $Source -File -Recurse)){
    Rename-Item $File.Fullname ($File.Name -replace " ", "-")
    $file.Name = ($File.Name -replace " ", "-")
    New-Item "$($Destination)\$($File.Name.Substring(0,3))" -ItemType directory
    move-item $File.FullName -force -destination $Destination\$($File.Name.Substring(0,3))
}
Crono
  • 10,211
  • 6
  • 43
  • 75
ArcSet
  • 6,518
  • 1
  • 20
  • 34
  • @vrdse your PoC environment has been useful thank you. I'm working on renaming duplicates, i'd like it to follow the format: FileName(1).ext FileName(2).ext etc but am having some difficulties with my while statement. I've updated my original post to reflect the current code. Again thank you for all of your assistance. – Jimmy Aug 20 '17 at 16:41