question

DaveRamsay-3420 avatar image
0 Votes"
DaveRamsay-3420 asked DaveRamsay-3420 commented

Powershell - Copy all jpg files and rename duplicates

Hi, I am new to Poweshell and it seems to be a solution for what I am trying to do but I cannot figure out the correct code to use. I am trying to copy all .jp files from my backup drive E: to a directory on the same drive E:\Photo_Backup

I have many duplicate file names in many back up directories which I would like to move to E:\Photo_Backup with no other sub directories. How can this be accomplished by keeping the original file names but appending 1,2,3, etc. to each name to differentiate between the files?

My goal is to review the files that are the same size and similar name and then delete the ones I don't want which are filling up my back up drive.

Thanks.

Dave

windows-server-powershell
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

This is the code I have tried but it copies every file type and I don't know where to insert the filter to only get jpg files.

function fcopy ($SourceDir,$DestinationDir)
{
Get-ChildItem $SourceDir -Recurse | Where-Object { $.PSIsContainer -eq $false } | ForEach-Object ($) {
$SourceFile = $.FullName
$DestinationFile = $DestinationDir + $

if (Test-Path $DestinationFile) {
$i = 0
while (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = $DestinationDir + $.basename + $i + $.extension
}
} else {
Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
}
}
fcopy -SourceDir "E:\" -DestinationDir "E:\Photo_Backup\"

0 Votes 0 ·
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered DaveRamsay-3420 commented

See if this works:

 Function fcopy ($SourceDir, $DestinationDir)
 {
     Get-ChildItem $SourceDir -Recurse -File -Include *.jpg |
         Where-Object {$_.FullName -notlike "$DestinationDir*"} |    # Do *NOT* venture into the directory you're moving files to!!!
             ForEach-Object {
                 $SourceFile = $_.FullName
                 $DestinationFile = $DestinationDir + $_.Name
                 if (Test-Path $DestinationFile) {
                     $i = 0
                     while (Test-Path $DestinationFile) {
                         $DestinationFile = "{0}{1}{2}{3}" -f $DestinationDir, $_.Basename, $i++, $_.Extension
                     }
                 }
                 Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
             }
 }
    
 fcopy -SourceDir "E:\" -DestinationDir "E:\Photo_Backup\"

The problem is that the Get-ChildItem is including the files your destination directory because the destination directory is a child of your source directory.

· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you as well for trying to help me. I pasted your code above in its entirety but no luck I'm afraid.

 $.FullName : The term '$.FullName' is not recognized as the name of a cmdlet, function, script file, or operable
 program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
 At line:6 char:32
 +                  $SourceFile = $.FullName
 +                                ~~~~~~~~~~
     + CategoryInfo          : ObjectNotFound: ($.FullName:String) [], CommandNotFoundException
     + FullyQualifiedErrorId : CommandNotFoundException
    
 Copy-Item : Cannot bind argument to parameter 'Path' because it is null.
 At line:14 char:34
 +                  Copy-Item -Path $SourceFile -Destination $Destinatio ...
 +                                  ~~~~~~~~~~~
     + CategoryInfo          : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
     + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCom
    mand
0 Votes 0 ·

Remember what I said about the normal editor munging code? I'd copied what you'd posted and I missed correcting the missing "_" after the "$" on line 6.

I'll fix the code I posted (adding that missing "_"). Copy the corrected code sample and try again.

0 Votes 0 ·

Bingo! That solved my challenge, thank you very much.

Dave

0 Votes 0 ·
cooldadtx avatar image
0 Votes"
cooldadtx answered cooldadtx commented

To filter on only the files you care about add the Include parameter to your Get-ChildItem call.

Get-ChildItem $sourceDir -Recurse -Include *.jpg


Note that you should also probably put a -File on the call so you only get the files you care about.

· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you very much. I updated line 1 as indicated but not sure where to put -File? I am a beginner as of today!

0 Votes 0 ·

With the Get-ChildItem call.

Get-ChildItem $sourceDir -Recurse -Include *.jpg -File
1 Vote 1 ·
DaveRamsay-3420 avatar image
0 Votes"
DaveRamsay-3420 answered DaveRamsay-3420 commented

Thank you again. It seems that this may not like the sub directory folder names that Seagate created or my code needs some enhancing? When I look at the error message it appears that the Destination is not only E:\Photo_Backup, but also the sub directories the files reside in. Hope my comment makes sense.

The copy worked before I added the filter but the code grabbed all files regardless of the extension and put them in the E:\Photo_Backup directory. Not sure why I am getting error messages now.

VERBOSE: Performing the operation "Copy File" on target "Item: E:\Seagate Dashboard
2.0\DAVES-NEW-HP-AL\2rams\Backup\6f4eff08-67aa-44c7-a519-a0a459d1f9e5\20211018_235910_2ramsInc117\C\Users\2rams\OneDriv
e\Pictures\Emma and Ivey Fall 2021 Photo Shoot\highlights\21Fall.jpg Destination: E:\Photo_Backup\E:\Seagate Dashboard
2.0\DAVES-NEW-HP-AL\2rams\Backup\6f4eff08-67aa-44c7-a519-a0a459d1f9e5\20211018_235910_2ramsInc117\C\Users\2rams\OneDriv
e\Pictures\Emma and Ivey Fall 2021 Photo Shoot\highlights\21Fall.jpg".
Copy-Item : The given path's format is not supported.
At line:13 char:13
+ Copy-Item -Path $SourceFile -Destination $DestinationFile ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], NotSupportedException
+ FullyQualifiedErrorId : System.NotSupportedException,Microsoft.PowerShell.Commands.CopyItemCommand

=====================================================================================

Here is the code I ran which resulted in the error message above..........................

**function fcopy ($SourceDir,$DestinationDir)
{
Get-ChildItem $sourceDir -Recurse -Include .jpg -File | Where-Object { $.PSIsContainer -eq $false } | ForEach-Object ($) {
$SourceFile = $.FullName
$DestinationFile = $DestinationDir + $

if (Test-Path $DestinationFile) {
$i = 0
while (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = $DestinationDir + $.basename + $i + $.extension
}
} else {
Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
}
}
fcopy -SourceDir "E:\" -DestinationDir "E:\Photo_Backup\"
*

· 9
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Photo Shoot\highlights\21Fall.jpg Destination: E:\Photo_Backup\E:\Seagate Dashboard

The concatenated path is combining your base destination directory to the full path to the original file (E:...E:). Try this.

$files = get-childitem $sourceDir -filter *.jpg -recurse
foreach ($file in $files) {
   $index = 1
   $destinationFile = [IO.Path]::Combine($destinationDir, $file.Name) 
   while (Test-Path $destinationFile) {                                                                                
      $destinationFile = [IO.Path]::Combine($destinationDir, [IO.Path]::GetFileNameWithoutExtension($file) + $index + [IO.Path]::GetExtension($file))                                                      
      $index++
   }                                                                                                                   
  Copy-Item -Path $file -Destination $destinationFile                                                 
}

I switched to filter because it works better when you are trying to match files in the source directory as well as subfolders.

0 Votes 0 ·

I really appreciate your help and sorry to take up your time. I replaced my code with the one you just provided but now getting other error messages. The source drive is E:\ and there are 2 directories then many sub directories after that. The 2 main directories are: Seagate Dashboard 2.0 and Toolkit. Each of these has hundreds of sub directories to pull the jpg files from. By replacing my previous code with the new one I don't see how it knows the source and destination.


Copy-Item : Cannot find path 'E:\20210917_000516000_iOS.jpg' because it does not exist.
At line:9 char:3
+ Copy-Item -Path $file -Destination $destinationFile
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (E:\20210917_000516000_iOS.jpg:String) [Copy-Item], ItemNotFoundExceptio
n
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand


0 Votes 0 ·

In your original post you gave the code as a function that accepts the source and destination directories. Piecing together the other comments you made I'm going to assume that the source dir is E:\seagate dashboard 2.0. The destination dir is E:\Photo_backup. So if you need to run this against 2 different source directories you'll run your function twice.

fcopy -sourceDir 'e:\seagate dashboard 2.0' -destinationDir 'e:\photo_backup'
fcopy -sourceDir 'e:\Toolkit` -destinationDir 'e:\photo_backup'


It is important to note that you cannot have your destination directory be a subdirectory of your source directory. If it were then when you recursively requested all the files on the source you'd also get picking up the files in the destination directory.

0 Votes 0 ·
Show more comments

When you post code, please use the "Code Sample" editor to do so. It's the 5th icon from the left on the format bar (the one with the "101 010" icon).

The normal editor mangles code. It removes some elements (like the "_" after a "$"), assumes lines that begin with "#" are something other than a comment, etc.

Using the normal editor to post code also makes it difficult to separate code from other text.

0 Votes 0 ·

Thank you for the instructions to use the Code Sample editor, I was wondering how that worked!

0 Votes 0 ·