How to copy individual files & rename duplicates with PowerShell

Black and White PDQ logo
Kris Powell|January 8, 2015
How to Copy Individual Files and Rename Duplicates with Powershell
How to Copy Individual Files and Rename Duplicates with Powershell

There are many factors to consider when copying files within a script.

In many instances, we check for the existence of a file and only copy the file if it does not exist. Sometimes we only copy if it’s older/newer than a certain file. Sometimes we only copy if the file sizes are different…and so on and so forth.

I’m sure that you get the idea. There are many things to consider.

For this particular case, I wanted to keep all copies and rename any duplicates sequentially. I will be using Copy-Item to get this done.

Copy-Item

Normally, when using Copy-Item, you’ll find that it will overwrite any destination files. It will not create any nonexistent folders in your destination file path.

For example, if you try to copy the source file to a new location that doesn’t exist yet, you will see a similar error:

Copy Item Fails Nonexistent Directory

In this case, the C:\Temp\File.txt file exists but the subdirectory does not, as it mentions in the error above.

The only way to get Copy-Item to create the subdirectories if they don’t already exist is to copy a directory recursively. Unfortunately, it will not work with individual files, so it is out of the scope for this post.

Test-Path and New-Item

One of the simplest ways to get the nonexistent directories created when copying individual files is to test for missing files and manually create the file before you copy (similar to unix/linux “touch” command).

In order to verify if a file already exists, we will use the Test-Path cmdlet. Test-Path can verify if a file or folder exists. When using Test-Path, items that exist will return $true whereas items that do not exist (or cannot be verified) will return $false:

Powershell Test Path Examples

Once we’ve verified that a file doesn’t exist, we can use New-Item to create a placeholder for the file we’re about to copy. Unlike Copy-Item, New-Item can create the nonexistent directory structure when creating new files.

Copying files and creating any nonexistent subdirectories

Here’s an example of creating the destination file before copying (in order to create the destination file’s directory structure):

############################################################################# $SourceFile = "C:\Temp\File.txt" $DestinationFile = "C:\Temp\NonexistentDirectory\File.txt" If ((Test-Path $DestinationFile) -eq $false) { New-Item -ItemType File -Path $DestinationFile -Force } Copy-Item -Path $SourceFile -Destination $DestinationFile #############################################################################

Breaking it down:

First, we test if $DestinationFile exists by using Test-Path. If the result of that Test-Path is false, we create an empty file by using the New-Item cmdlet.

The New-Item cmdlet will create our file. Using -Force here tells New-Item to create all the directories necessary for that particular file.

Finally, we are able to successfully use the Copy-Item command to copy the $SourceFile to the newly-created $DestinationFile.

As awesome as this is, it only gets us partially there. The normal behavior for Copy-Item will overwrite the destination file (with or without -Force). We’re trying to preserve all files and create duplicate destination files instead of overwriting.

Copying individual files and renaming any duplicates

Here is a simple way to copy a file from one location to another while preserving all destination files. We increment the destination file names:

############################################################################# $SourceFile = "C:\Temp\File.txt" $DestinationFile = "C:\Temp\NonexistentDirectory\File.txt" If (Test-Path $DestinationFile) { $i = 0 While (Test-Path $DestinationFile) { $i += 1 $DestinationFile = "C:\Temp\NonexistentDirectory\File$i.txt" } } Else { New-Item -ItemType File -Path $DestinationFile -Force } Copy-Item -Path $SourceFile -Destination $DestinationFile -Force #############################################################################

Breaking it down:

We test if the path $DestinationFile exists by using Test-Path. We then check if the file name already exists.

If $DestinationFile doesn’t exist, it will create the file and then copy the source over the destination file.

If $DestinationFile does already exist, it will jump into a While loop. It will modify the Destination File name by incrementing part of the name, testing each modified name until it finds a name that doesn’t match an existing file.

If File.txt doesn’t exist, it will create File.txt first. Subsequent runs will create, File1.txt, File2.txt, File3.txt and so forth.

Keep in mind that copying large or numerous files will result in increased disk usage, so be sure to keep an eye on your utilization.

Disclaimer and side notes

Use these scripts at your own risk. Be sure you understand what you’re doing before using these in a production environment. As always, feel free to modify these to suit your environment.

I realize that there are many ways to tackle the issues above. In fact, the latest estimates place the possibilities at around 1.2 bajillion, though scientists predict even greater numbers.

Additional resources and tools for copying/moving/deleting files are also available, such as one of my favorite tools for copying: Robocopy.

Good luck!

Did you know that PDQ Deploy has a PowerShell step you can use to deploy your scripts?

Black and White PDQ logo
Kris Powell

Kris was an employee at PDQ.

Related articles