Copiar arquivos eficientemente com Copy-Item do PowerShell: Um Guia Abrangente

Copiando arquivos. Não é sexy, mas precisa ser feito. Na GUI, copiamos e colamos com a área de transferência, mas no PowerShell temos um cmdlet chamado Copy-Item.

Comandos para copiar arquivos existem há muito tempo em todas as linguagens de shell. No PowerShell, a maneira mais popular de obter uma cópia de um arquivo ou pasta em seu script PowerShell do ponto A para o ponto B é usando o cmdlet Copy-Item do PowerShell. Este cmdlet nos permite copiar um arquivo e pasta, ao mesmo tempo que nos dá a capacidade de percorrer arquivos em uma pasta, usar caracteres curinga para selecionar os arquivos que precisamos copiar e até mesmo usar PowerShell Remoting para copiar um arquivo!

Este cmdlet faz parte dos cmdlets do provedor do PowerShell. É um cmdlet genérico reconhecido pelo seu nome Item. A maioria desses cmdlets do provedor pode ser usada em diferentes provedores, mas em quase 10 anos usando o PowerShell, só vi o Copy-Item ser usado com o provedor do sistema de arquivos.

Ao usar este cmdlet, o PowerShell permite que um desenvolvedor copie arquivos e pastas de várias maneiras diferentes.

Uso Básico

No seu uso mais básico, o cmdlet Copy-Item copia um único arquivo do ponto A para o ponto B usando o parâmetro Path como o caminho de origem do arquivo e o parâmetro Destination como o caminho da pasta de destino.

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 

Este cmdlet também pode copiar pastas vazias. Vou listar itens na pasta C:\EmptyFolder e então copiá-los.

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 

Talvez haja um arquivo somente leitura na pasta. Por padrão, o Copy-Item não o sobrescreverá. Para forçar a substituição, basta adicionar o parâmetro Force.

Selecionando com Copy-Item

Além de copiar um único arquivo ou pasta, também podemos copiar todo o conteúdo de uma pasta. O parâmetro Path do Copy-Item aceita caracteres curinga como o asterisco para corresponder a um ou mais caracteres ou o ponto de interrogação para corresponder apenas a um caractere.

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

Fundindo Múltiplas Pastas Juntas

Outra característica legal do Copy-Item é sua capacidade de copiar várias pastas juntas ao mesmo tempo. Ao passar vários caminhos para o parâmetro Path, o Copy-Item analisará cada um, copiará a pasta ou arquivo(s) dependendo do caminho e os “fundirá” todos no destino único.

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

Copiando Arquivos Recursivamente

Provavelmente você não terá sorte e terá todos os arquivos em uma única pasta sem pastas lá dentro também. Normalmente nos deparamos com situações em que temos muitas subpastas na pasta pai com arquivos nelas também que gostaríamos de copiar. Usando o parâmetro Recurse no Copy-Item, ele com prazer procurará em cada subpasta e copiará todos os arquivos e pastas em cada uma recursivamente.

Observe aqui que estou encaminhando arquivos e pastas diretamente de Get-ChildItem para Copy-Item. Copy-Item tem suporte para pipeline!

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

Vantagens de usar o Parâmetro PassThru

Muitos cmdlets no PowerShell possuem um parâmetro PassThru. Cmdlets que normalmente não retornam nada podem devolver os objetos que estão sendo manipulados usando o parâmetro PassThru. Este cmdlet não é diferente. Quando comecei a escrever scripts, nunca usei esse parâmetro porque não achava necessário.

Por exemplo, se eu quisesse copiar um arquivo para um local remoto e depois referenciar esse arquivo mais tarde no meu script, eu faria algo assim:

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

Este método funciona, mas pode ser melhor. Em vez de definir uma variável para o caminho remoto, por que não capturar apenas o objeto retornado pelo cmdlet Copy-Item ao usar o parâmetro PassThru? Os objetos retornados sempre terão o caminho do arquivo de destino.

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

Copiando Arquivos Usando uma Sessão Remota do PowerShell

Uma funcionalidade interessante que veio com o PowerShell v5 é a capacidade deste cmdlet de não usar o protocolo SMB padrão para transferir um arquivo, mas sim usar o WinRM e uma sessão remota do PowerShell. Ao usar o parâmetro Session, Copy-Item utiliza uma sessão existente do PowerShell e transfere os arquivos dessa maneira. Esta é uma ótima maneira de contornar firewalls e, quando a comunicação da sessão é criptografada, oferece uma camada extra de segurança.

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

Nós poderíamos ter copiado o arquivo File.txt pela SMB e esperado que o compartilhamento administrativo C$ estivesse disponível, e usado o caminho de destino \\WEBSRV1\c$. Como usamos o parâmetro ToSession em vez disso, o caminho de destino será sempre o caminho local ao computador em que a sessão remota está em execução.

Resumo

O cmdlet Copy-Item é um daqueles cmdlets essenciais do PowerShell que você usará repetidamente. No PowerShell, copie arquivos e pastas de várias maneiras diferentes com sua simplicidade, mas poderosa, especialmente com sua capacidade de usar caracteres curinga, mesclar várias pastas de arquivos e usar sessões de Remoting do PowerShell existentes!

Leitura Adicional

Copy-item

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