Copying files between folders, drives and machines is a common administrative task that PowerShell can simplify.
Administrators who understand the parameters associated with the Copy-Item commands and how they work together will get the most from the PowerShell commands to copy files.
PowerShell has providers — .NET programs that expose the data in a data store for viewing and manipulation — and a set of common cmdlets that work across providers.
Therefore, you can use the Copy-Item cmdlet to copy files, Registry keys and variables.
How to use Copy-Item command
The example in the following command uses variable $a:
Copy-Item -Path variable:a -Destination variable:aa
When working with databases, administrators commonly use transactions — one or more commands treated as a unit — so the commands either all work or they all roll back. PowerShell transactions are only supported by the Registry provider, so the UseTransaction parameter on Copy-Item doesn’t do anything. The UseTransaction parameter is part of Windows PowerShell v2 through v5.1, but not in the open source PowerShell Core.
PowerShell has a number of aliases for its major cmdlets. Copy-Item uses three aliases.
Get-Alias -Definition copy-item
CommandType Name Version Source
----------- ---- ------- ------
Alias copy -> Copy-Item
Alias cp -> Copy-Item
Alias cpi -> Copy-Item
These aliases only exist on Windows PowerShell to prevent a conflict with native Linux commands for PowerShell Core users.
Ways to use PowerShell commands to copy files
To show how the various Copy-Item parameters work, create a test file with the following command:
Get-Process | Out-File -FilePath c:\test\p1.txt
Use this command to copy a file:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\
The issue with this command is there is no indication if the operation succeeds or fails.
When working interactively, you can use the alias and positional parameters to reduce typing.
Copy C:\test\p1.txt C:\test2\
While this works in scripts, it makes the code harder to understand and maintain.
To get feedback on the copy, we use the PassThru parameter:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\ -PassThru
Directory: C:\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 13/08/2018 11:01 40670 p1.txt
Or we can use the Verbose parameter:
The Verbose parameter gives you information as the command executes, while PassThru shows you the result.
By default, PowerShell overwrites the file if a file with the same name exists in the target folder. If the file in the target directory is set to read-only, you’ll get an error.
This article is part of
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\
Copy-Item : Access to the path 'C:\test2\p1.txt' is denied.
At line:1 char:1
+ Copy-Item -Path C:\test\p1.txt -Destination C:\test2\
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\test\p1.txt:FileInfo) [Copy-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : CopyFileInfoItemUnauthorizedAccessError,
Microsoft.PowerShell.Commands.CopyItemCommand
You need to be a PowerShell Jedi to overcome this. Use the Force parameter:
Copy-Item -Path C:\test\p1.txt -Destination C:\test2\ -Force
As part of the copy process, you can rename the file. You must include the new file name as part of the destination. For example, this code creates nine copies of the p1.txt file called p2.txt through p10.txt.
2..10 | foreach {
$newname = "p$_.txt"
Copy-Item -Path C:\test\p1.txt -Destination C:\test\$newname
}
PowerShell commands to copy multiple files or folders
There are a few techniques to copy multiple files when using PowerShell.
Copy-Item -Path C:\test\*.txt -Destination C:\test2\
Copy-Item -Path C:\test\* -Filter *.txt -Destination C:\test2\
Copy-Item -Path C:\test\* -Include *.txt -Destination C:\test2\
These commands copy all the .txt files from the test folder to the test2 folder, but you can also be more selective and only copy files with, for instance, a 6 in the name.
Copy-Item -Path C:\test\* -Include *6*.txt -Destination C:\test2\ -PassThru
Directory: C:\test2
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 13/08/2018 11:01 40670 p6.txt
-a---- 13/08/2018 11:01 40670 x6.txt
You can also exclude certain files from the copy operation. This command copies all the text files that start with the letter p unless there is a 7 in the name:
Copy-Item -Path C:\test\* -Filter p*.txt -Exclude *7*.txt -Destination C:\test2\
You can combine the Path, Filter, Include or Exclude parameters to define exactly what to copy. If you use Include and Exclude in the same call, PowerShell ignores Exclude. You can also supply an array of file names. The path is simplified if your working folder is the source folder for the copy.
Copy-Item -Path p1.txt,p3.txt,x5.txt -Destination C:\test2\
The Path parameter accepts pipeline input.
Get-ChildItem -Path C:\test\p*.txt |
where {(($_.BaseName).Substring(1,1) % 2 ) -eq 0} |
Copy-Item -Destination C:\test2\
PowerShell checks the p*.txt files in the c:\test folder to see if the second character is divisible by 2. If so, PowerShell copies the file to the C:\test2 folder.
[embedded content]
How to use PowerShell cmdlets to copy, move
and delete files
If you end up with a folder or file name that contains wild-card characters, use the LiteralPath parameter instead of the Path parameter. LiteralPath treats all the characters as literals and ignores any possible wild-card implications.
To copy a folder and all its contents, use the Recurse parameter.
Copy-Item -Path c:\test\ -Destination c:\test2\ -Recurse
The recursive copy will work its way through all the subfolders below the c:\test folder. PowerShell will then create a folder named test in the destination folder and copy the contents of c:\test into it.
When copying between machines, you can use UNC paths to bypass the local machine.
Copy-Item -Path \\server1\fs1\test\p1.txt -Destination \\server2\arc\test\
Another option is to use PowerShell commands to copy files over a remoting session.
$cred = Get-Credential -Credential W16ND01\Administrator
$s = New-PSSession -VMName W16ND01 -Credential $cred
In this case, we use PowerShell Direct to connect to the remote machine. You’ll need the Hyper-V module loaded to create the remoting session over the VMBus. Next, use PowerShell commands to copy files to the remote machine.
Copy-Item -Path c:\test\ -Destination c:\ -Recurse -ToSession $s
You can also copy from the remote machine.
Copy-Item -Path c:\test\p*.txt -Destination c:\test3\ -FromSession $s
The ToSession and FromSession parameters control the direction of the copy and whether the source and destination are on the local machine or a remote one. You can’t use ToSession and FromSession in the same command.
Copy-Item doesn’t have any error checking or restart capabilities. For those features, you’ll need to write the code. Here is a starting point:
function Copy-FileSafer {
[CmdletBinding()]
param (
[string]$path,
[string]$destinationfolder
)
if (-not (Test-Path -Path $path)) {
throw "File not found: $path"
}
$sourcefile = Split-Path -Path $path -Leaf
$destinationfile = Join-Path -Path $destinationfolder -ChildPath $sourcefile
$b4hash = Get-FileHash -Path $path
try {
Copy-Item -Path $path -Destination $destinationfolder -ErrorAction Stop
}
catch {
throw "File copy failed"
}
finally {
$afhash = Get-FileHash -Path $destinationfile
if ($afhash.Hash -ne $b4hash.Hash) {
throw "File corrupted during copy"
}
else {
Write-Information -MessageData "File copied successfully" -InformationAction Continue
}
}
}
In this script, the file path for the source is tested and a hash of the file is calculated. The file copy occurs within a try-catch block to catch and report errors.
With additional coding, the script can recursively retry a certain number of times. After each copy attempt, the script can calculate the hash of the file and compare it to the original. If they match, all is well. If not, an error is reported.
Leave a Reply