Copia File Efficientemente con PowerShell Copy-Item: Una Guida Completa

Copiando file. Non è sexy ma deve essere fatto. Nell’interfaccia grafica, copiamo e incolliamo con gli appunti, ma in PowerShell abbiamo un cmdlet chiamato Copy-Item.

I comandi per copiare file sono esistiti da sempre in tutti i linguaggi di shell. Nel mondo di PowerShell, il modo più popolare per ottenere una copia di un file o di una cartella all’interno di uno script PowerShell da A a B è utilizzare il cmdlet PowerShell Copy-Item. Questo cmdlet ci permette di copiare un file o una cartella, dandoci la possibilità di ricorsivamente copiare i file all’interno di una cartella, utilizzare caratteri jolly per selezionare i file da copiare e persino utilizzare PowerShell Remoting per una copia di file!

Questo cmdlet fa parte dei cmdlet del provider PowerShell. È un cmdlet generico riconosciuto dal suo sostantivo Item. La maggior parte di questi cmdlet provider può essere utilizzata con diversi provider, ma nei quasi 10 anni in cui ho utilizzato PowerShell, ho visto utilizzare solo Copy-Item con il provider del file system.

Utilizzando questo cmdlet, PowerShell consente a uno sviluppatore di copiare file e cartelle in diversi modi.

Utilizzo di base

Nel suo utilizzo più semplice, il cmdlet Copy-Item copia un singolo file da A a B utilizzando il parametro Path come percorso del file sorgente e il parametro Destination come percorso della cartella di destinazione.

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 

Questo cmdlet può anche copiare cartelle vuote. Elenco gli elementi nella cartella C:\EmptyFolder e poi li copio.

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 

Forse c’è un file in sola lettura nella cartella. Per impostazione predefinita, Copy-Item non lo sovrascriverà. Per forzare la sovrascrittura, aggiungi semplicemente il parametro Force.

Diventare selettivi con Copy-Item

Oltre a copiare un singolo file o cartella, possiamo anche copiare l’intero contenuto di una cartella. Il parametro Path di Copy-Item accetta caratteri jolly come l’asterisco per corrispondere a uno o più caratteri o il punto interrogativo per corrispondere solo a un singolo carattere.

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

Unire più cartelle insieme

Un’altra caratteristica interessante di Copy-Item è la sua capacità di copiare contemporaneamente più cartelle insieme. Passando più percorsi al parametro Path, Copy-Item esaminerà ognuno di essi, copierà la cartella o il/i file a seconda del percorso e li “unirà” tutti nella destinazione singola.

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

Copiare file ricorsivamente

Probabilmente non avrai la fortuna di avere tutti i file in una singola cartella senza altre cartelle al suo interno. Di solito ci imbattiamo in situazioni in cui abbiamo un sacco di sottocartelle nella cartella principale con file al loro interno che vorremmo copiare. Utilizzando il parametro Recurse su Copy-Item, guarderà volentieri in ogni sottocartella e copierà tutti i file e le cartelle in modo ricorsivo.

Nota che sto inviando i file e le cartelle direttamente da Get-ChildItem a Copy-Item. Copy-Item supporta il piping!

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

Vantaggi dell’utilizzo del parametro PassThru

Molti cmdlet in PowerShell hanno un parametro PassThru. I cmdlet che di solito non restituiscono nulla possono restituire gli oggetti che stanno manipolando utilizzando il parametro PassThru. Questo cmdlet non fa eccezione. Quando ho iniziato a scrivere script, non ho mai usato questo parametro perché non pensavo di averne bisogno.

Ad esempio, se volessi copiare un file in una posizione remota e poi fare riferimento a quel file in seguito nello script, farei qualcosa del genere:

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

Questo metodo funziona, ma può essere migliorato. Invece di definire una variabile per il percorso remoto, perché non catturare direttamente l’oggetto restituito dal cmdlet Copy-Item utilizzando il parametro PassThru? Gli oggetti restituiti avranno sempre il percorso del file di destinazione.

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

Copia dei file utilizzando una sessione di PowerShell remota

Una caratteristica interessante introdotta con PowerShell v5 è la capacità di questo cmdlet di non utilizzare il protocollo SMB predefinito per il trasferimento di un file, ma invece utilizzare WinRM e una sessione remota di PowerShell. Utilizzando il parametro Session, Copy-Item utilizza una sessione di PowerShell esistente e trasferisce i file in questo modo. Questo è un ottimo modo per aggirare i firewall e, quando la comunicazione della sessione è crittografata, offre anche un ulteriore livello di sicurezza.

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

Avremmo potuto copiare il file File.txt tramite SMB e sperare che la condivisione amministrativa C$ fosse disponibile e utilizzare il percorso di destinazione \\WEBSRV1\c$. Poiché abbiamo utilizzato invece il parametro ToSession, il percorso di destinazione sarà sempre il percorso locale al computer in cui viene eseguita la sessione remota.

Riepilogo

Il cmdlet Copy-Item è uno di quei cmdlet di base di PowerShell che userai sempre e sempre. In PowerShell, copia file e cartelle in diversi modi grazie alla sua semplicità ma potenza, soprattutto con la sua capacità di utilizzare caratteri jolly, di unire più cartelle di file insieme e di utilizzare sessioni di PowerShell Remoting esistenti!

Lettura ulteriore

Copy-item

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