Comando cp: copia correttamente le cartelle di file in *nix

Comando cp: copia correttamente le cartelle di file in *nix

Questo articolo rivelerà alcune cose non ovvie relative all'uso di jolly durante la copia, comportamento ambiguo dei comandi cp durante la copia, nonché metodi che consentono di copiare correttamente un numero enorme di file senza saltare o bloccarsi.

Diciamo che dobbiamo copiare tutto dalla cartella /source alla cartella /target.

La prima cosa che mi viene in mente è:

cp /source/* /target

Correggiamo immediatamente questo comando in:

cp -a /source/* /target

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

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

.profile
.local
.mc

e simili.

Perché è successo?

Poiché i caratteri jolly vengono elaborati dalla shell (bash in un caso tipico). Per impostazione predefinita, bash ignorerà tutti i file che iniziano con punti, poiché li tratta come nascosti. Per evitare questo comportamento dovremo cambiare comportamento bash utilizzando il comando:

shopt -s dotglob

Per garantire che questa modifica di comportamento persista dopo un riavvio, è possibile creare un file wildcard.sh con questo comando nella cartella /etc/profile.d (Forse la tua distribuzione ha una cartella diversa).

E se non ci sono file nella directory di origine, la shell non sarà in grado di sostituire nulla al posto dell'asterisco e anche la copia fallirà con un errore. Ci sono opzioni contro questa situazione failglob и nullglob. Dovremo sistemarci failglob, che impedirà l'esecuzione del comando. nullglob non funzionerà, poiché converte una stringa con caratteri jolly che non ha trovato corrispondenza in una stringa vuota (lunghezza zero), che per cp causerà un errore.

Tuttavia, se nella cartella sono presenti migliaia o più file, l'approccio con caratteri jolly dovrebbe essere abbandonato del tutto. Il fatto è che bash espande i caratteri jolly in una riga di comando molto lunga come:

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

Esiste un limite alla lunghezza della riga di comando, che possiamo scoprire utilizzando il comando:

getconf ARG_MAX

Otteniamo la lunghezza massima della riga di comando in byte:

2097152

Oppure:

xargs --show-limits

Otteniamo qualcosa del tipo:

….
Maximum length of command we could actually use: 2089314
….

Quindi, facciamo del tutto a meno dei caratteri jolly.

Scriviamo e basta

cp -a /source /target

E qui ci troviamo di fronte ad un'ambiguità di comportamento cp. Se la cartella /target non esiste, otterremo ciò di cui abbiamo bisogno.

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

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

Se le cartelle di origine e di destinazione avessero lo stesso nome, ad esempio, stessimo copiando da /source a /home/source, allora potremmo utilizzare il comando:

cp -a /source /home

E dopo la copia, i file in /home/source verrebbero integrati con i file da /source.

Questo è un problema logico: possiamo aggiungere file nella directory di destinazione se le cartelle hanno lo stesso nome, ma se sono diverse, la cartella di origine verrà posizionata all'interno di quella di destinazione. Come copiare file da /source a /target utilizzando cp senza caratteri jolly?

Per aggirare questa dannosa limitazione utilizziamo una soluzione non ovvia:

cp -a /source/. /target

Chi ha dimestichezza con DOS e Linux ha già capito tutto: all’interno di ogni cartella ci sono 2 cartelle invisibili”. e "..", che sono collegamenti di pseudo-cartelle alle directory correnti e superiori.

  • Durante la copia cp verifica l'esistenza e tenta di creare /target/.
  • Tale directory esiste ed è /target
  • I file da /source vengono copiati correttamente in /target.

Quindi, appendilo in una cornice audace nella tua memoria o sul muro:

cp -a /source/. /target

Il comportamento di questo comando è chiaro. Tutto funzionerà senza errori, indipendentemente dal fatto che tu abbia un milione di file o nessuno.

risultati

Se hai bisogno di copiare tutti file da una cartella all'altra, non usiamo i caratteri jolly, è meglio usarli invece cp combinato con un punto alla fine della cartella di origine. Questo copierà tutti i file, compresi quelli nascosti, e non fallirà con milioni di file o nessun file.

postfazione

vmspike ha suggerito una versione del comando con un risultato simile:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

NOTA: custodia per lettere T ha il significato. Se mescoli, otterrai una totale spazzatura: la direzione della copia cambierà.
grazie:

  • società RUVDS.COM per il supporto e l'opportunità di pubblicare sul tuo blog su Habré.
  • Per immagine Triplice concetto. L'immagine è molto grande e dettagliata, può essere aperta in una finestra separata.

PS Si prega di inviare eventuali errori notati in un messaggio privato. Aumento il mio karma per questo.

Comando cp: copia correttamente le cartelle di file in *nix

Fonte: habr.com

Aggiungi un commento