使用 PowerShell Copy-Item 高效复制文件:全面指南

拷贝文件。这并不起眼,但必须完成。在图形用户界面中,我们使用剪贴板进行复制和粘贴,但在PowerShell中,我们有一个称为Copy-Item的cmdlet。

复制文件的命令在所有Shell语言中都存在已经很久了。在PowerShell领域,将文件或文件夹从A点复制到B点的最流行方式是使用PowerShell Copy-Item cmdlet。这个cmdlet允许我们复制文件和文件夹,同时可以递归文件夹中的文件,使用通配符选择需要复制的文件,甚至可以使用PowerShell Remoting进行文件复制!

这个Copy-Item cmdlet是PowerShell提供程序 cmdlets的一部分。它是一个通用的cmdlet,以其Item名词而被识别。这些提供程序cmdlet中的大多数可以跨不同的提供程序使用,但在我使用PowerShell的近10年中,我只看到过Copy-Item与文件系统提供程序一起使用。

通过使用此cmdlet,PowerShell允许开发人员以多种不同的方式复制文件和文件夹。

基本用法

在其最基本的形式中,Copy-Item cmdlet使用Path参数作为源文件路径,Destination参数作为目标文件夹路径,将单个文件从A点复制到B点。

PS> Test-Path -Path C:\PointB\1.txt
False
PS> Copy-Item -Path C:\PointA\1.txt -Destination C:\PointB\
PS> Test-Path -Path C:\PointB\1.txt
True 

这个命令还可以复制空文件夹。我将在C:\EmptyFolder文件夹中列出项目,然后将它们复制出来。

PS> Get-ChildItem -Path C:\EmptyFolder\
PS> Test-Path -Path C:\PointB\EmptyFolder -PathType Container
False
PS> Copy-Item -Path C:\EmptyFolder\ -Destination C:\PointB\
PS> Test-Path -Path C:\PointB\EmptyFolder -PathType Container
True 

也许文件夹中有一个只读文件。默认情况下,Copy-Item不会覆盖它。要强制覆盖,只需添加Force参数。

使用Copy-Item进行选择性复制

除了复制单个文件或文件夹外,我们还可以复制文件夹的整个内容。Copy-Item的Path参数接受通配符字符,如星号匹配一个或多个字符,问号只匹配一个字符。

PS> @(Get-ChildItem -Path C:\PointB).Count
0
PS> @(Get-ChildItem -Path C:\PointA).Count
10000
PS> @(Get-ChildItem -Path C:\PointB).Count
0
PS> Copy-Item -Path C:\PointA\* -Destination C:\PointB\
PS> @(Get-ChildItem -Path C:\PointB).Count
10000
PS> @(Get-ChildItem -Path C:\PointB).Count
0
PS> Copy-Item -Path 'C:\PointA\26?0.txt' -Destination C:\PointB\
PS> Get-ChildItem -Path C:\PointB\

Directory: C:\PointB
Mode                LastWriteTime         Length Name
-a----        8/11/2017   8:59 AM              5 2600.txt
-a----        8/11/2017   8:59 AM              5 2610.txt
-a----        8/11/2017   8:59 AM              5 2620.txt
-a----        8/11/2017   8:59 AM              5 2630.txt
-a----        8/11/2017   8:59 AM              5 2640.txt
-a----        8/11/2017   8:59 AM              5 2650.txt
-a----        8/11/2017   8:59 AM              5 2660.txt
-a----        8/11/2017   8:59 AM              5 2670.txt
-a----        8/11/2017   8:59 AM              5 2680.txt
-a----        8/11/2017   8:59 AM              5 2690.txt

合并多个文件夹

Copy-Item的另一个很酷的功能是它可以同时复制多个文件夹。通过将多个路径传递给Path参数,Copy-Item将查看每个路径,根据路径复制文件夹或文件,并将它们全部“合并”到单个目标中。

PS> Copy-Item -Path C:\PointB\*,C:\PointC\*,C:\PointD\* -Destination C:\PointE
PS> Get-ChildItem -Path C:\PointE

Directory: C:\PointE
Mode                LastWriteTime         Length Name
-a----       11/11/2017  12:15 PM              2 PointBFile.txt
-a----       11/11/2017  12:15 PM              2 PointCFile.txt
-a----       11/11/2017  12:16 PM              4 PointDFile.txt

递归复制文件

很可能你不会走运,只有一个文件夹里面没有文件夹。通常我们会遇到这样的情况,父文件夹中有许多子文件夹,其中也有文件,我们希望将它们都复制过来。通过在Copy-Item上使用Recurse参数,它会很乐意查看每个子文件夹,并递归地复制其中的所有文件和文件夹。

请注意,这里我正在直接将文件和文件夹从Get-ChildItem管道传输到Copy-ItemCopy-Item支持管道!

PS> (Get-ChildItem -Path C:\PointB\ -Recurse).Count
5
PS> Get-ChildItem -Path C:\PointB\ | Copy-Item -Destination C:\PointC -Recurse
PS> (Get-ChildItem -Path C:\PointC\ -Recurse).Count
5

使用PassThru参数的优势

PowerShell中的许多cmdlet都有PassThru参数。通常不返回任何内容的cmdlet可以使用PassThru参数返回它们正在操作的对象。这个cmdlet也不例外。当我刚开始编写脚本时,我从未使用过这个参数,因为我觉得我不需要。

例如,如果我想将文件复制到远程位置,然后在脚本中稍后引用该文件,我会做这样的事情:

$remoteFilePath = '\WEBSRV1\c$\File.txt'
Copy-Item -Path C:\File.txt -Destination $remoteFilePath
Write-Host "I've just copied the file to $remoteFilePath"

这种方法有效,但可以更好。与其为远程路径定义一个变量,为什么不直接捕获使用PassThru参数时从Copy-Item cmdlet返回的对象呢?返回的对象将始终具有目标文件路径。

$copiedFile = Copy-Item -Path C:\File.txt -Destination '\WEBSRV1\c$'

使用PowerShell远程会话复制文件

PowerShell v5带来的一个很酷的功能是这个cmdlet的能力,它不使用默认的SMB协议来传输文件,而是使用WinRM和PowerShell远程会话。通过使用Session参数,Copy-Item使用现有的PowerShell会话并以这种方式传输文件。这是绕过防火墙的好方法,并且当会话通信被加密时,也提供了额外的安全层。

PS> $session = New-PSSession -ComputerName WEBSRV1
PS> Invoke-Command -Session $session -ScriptBlock { Test-Path -Path C:\File.txt }
False
PS> Copy-Item -Path C:\File.txt -ToSession $session -Destination 'C:\'
PS> Invoke-Command -Session $session -ScriptBlock { Test-Path -Path C:\File.txt }
True

我们可以通过SMB复制File.txt文件,并希望C$管理共享可用,并使用\\WEBSRV1\c$的目标路径。由于我们改用了ToSession参数,所以目标路径将始终是在远程会话所在计算机本地的路径。

摘要

Copy-Item cmdlet 是那些核心 PowerShell 命令中的一个,您会一遍又一遍地使用它。在 PowerShell 中,使用这个简单而强大的 cmdlet,可以以多种不同的方式复制文件、文件夹,特别是它能够使用通配符、将多个文件夹的文件合并在一起,并使用现有的 PowerShell 远程会话!

进一步阅读

Copy-item

Source:
https://adamtheautomator.com/copy-item/