Team cp: copia corretta di cartelle con file in *nix.

Team cp: copia corretta di cartelle con file in *nix.

In questo articolo verranno rivelate alcune cose non ovvie relative all'uso dei caratteri jolly durante la copia, il comportamento ambiguo del comando cp nella copia, oltre a modi per copiare correttamente grandi quantità di file senza perdite e errori.

Supponiamo di dover copiare tutto dalla cartella /source nella cartella /target.

La prima cosa che ci viene in mente è:

cp /source/* /target

Correggiamo subito questo comando in:

cp -a /source/* /target

Chiave -a aggiungerà la copia di tutti gli attributi, diritti e abiliterà la ricorsione. Quando non è necessaria una riproduzione esatta dei diritti, è sufficiente la chiave -r.

Dopo la copia scopriremo che non tutti i file sono stati copiati: sono stati ignorati i file che iniziano con un punto come ad esempio:

.profilo
.locale
.mc

e simili.

Perché è successo?

Perché i caratteri jolly vengono elaborati dalla shell (bash in un caso tipico). Per impostazione predefinita, bash ignorerà tutti i file che iniziano con punti, in quanto li considera nascosti. Per evitare questo comportamento, dovremo modificare il comportamento bash con il comando:

shopt -s dotglob

Per mantenere questa modifica anche dopo un riavvio, è possibile creare un file wildcard.sh con questo comando nella cartella /etc/profile.d (potrebbe esserci una cartella diversa nella tua distribuzione).

Se nella directory sorgente non ci sono file, allora il shell non potrà sostituire nulla al posto dell'asterisco, e così il copia termina con un errore. A fronte di questa situazione, ci sono opzioni. failglob e nullglob. Dobbiamo impostare failglob, che impedirà l'esecuzione del comando. nullglob non funzionerà, perché trasforma la stringa con wildcards che non hanno trovato corrispondenze in una stringa vuota (di lunghezza zero), il che per cp causerà un errore.

Tuttavia, se ci sono migliaia di file nella cartella, è meglio rinunciare all'approccio con le wildcards. Infatti, bash espande le wildcards in una stringa di comando molto lunga, simile a:

cp -a /souce/a /source/b /source/c …… /target

C'è un limite alla lunghezza della linea di comando, che possiamo scoprire usando il comando:

getconf ARG_MAX

Otterremo la lunghezza massima della linea di comando in byte:

2097152

O:

xargs --show-limits

Otterremo qualcosa come:

…. 
Lunghezza massima del comando che potremmo effettivamente usare: 2089314
….

Quindi, evitiamo completamente l'uso delle wildcards.

Semplicemente scriviamo

cp -a /source /target

E qui ci imbatteremo in un comportamento ambiguo cp. Se la cartella /target non esiste, otterremo ciò di cui abbiamo bisogno.

Tuttavia, se la cartella target esiste, i file verranno copiati nella cartella /target/source.

Non sempre possiamo eliminare in anticipo la cartella /target, poiché potrebbe contenere file necessari e il nostro obiettivo, ad esempio, è quello di integrare i file in /target con quelli in /source.

Se le cartelle di origine e destinazione avessero nomi identici, ad esempio, se copiassimo da /source a /home/source, sarebbe possibile utilizzare il comando:

cp -a /source /home

E dopo la copia, i file in /home/source sarebbero stati integrati con i file di /source.

Ecco un problema logico: possiamo integrare i file nella directory di destinazione se le cartelle hanno lo stesso nome, ma se sono diverse, la cartella di origine sarà posizionata all'interno della destinazione. Come copiare file da /source a /target usando cp senza wildcards?

Per aggirare questa limitazione dannosa, utilizziamo una soluzione non ovvia:

cp -a /source/. /target

Chi è ben familiare con DOS e Linux ha già capito tutto: all'interno di ogni cartella ci sono 2 cartelle invisibili «.» e «..», che fungono da collegamenti pseudocartella alla directory attuale e a quella superiore.

  • Durante la copia cp verifica l'esistenza e cerca di creare /target/.
  • Una tale directory esiste ed è /target.
  • I file da /source sono stati copiati in /target correttamente.

Quindi, annotiamolo bene nella nostra memoria o attacchiamolo al muro:

cp -a /source/. /target

Il comportamento di questo comando è chiaro. Funzionerà senza errori indipendentemente dal fatto che abbiate un milione di file o nessuno.

Conclusioni

Se è necessario copiare tutti file da una cartella all'altra, non usate i caratteri jolly, è meglio utilizzare cp insieme a un punto alla fine della cartella di origine. Questo copierà tutti i file, compresi quelli nascosti, e non si fermerà nemmeno con milioni di file o con l'assenza totale di file.

Epifania

vmspike ha suggerito un comando con risultati simili:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

ATTENZIONE: la lettera maiuscola T è importante. Se confondete, otterrete una confusione totale: la direzione di copia cambierà.
Ringraziamenti:

  • Compagnie RUVDS.COM per il supporto e la possibilità di pubblicazione sul loro blog su Habr.
  • Per l'immagine TripletConcept. L'immagine è molto grande e dettagliata, può essere aperta in una finestra separata.

P.S. Segnalate gli errori riscontrati in privato. Alzo la karma per questo.

Team cp: copia corretta di cartelle con file in *nix.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster