
In questo articolo verranno rivelate alcune cose non ovvie legate all'uso nella copia, il comportamento ambiguo del comando cp durante la copia, e anche i modi per copiare correttamente un enorme numero di file senza salti e crash.
Supponiamo di dover copiare tutto dalla cartella /source nella cartella /target.
La prima cosa che viene in mente è:
cp /source/* /targetCorreggiamo subito questo comando in:
cp -a /source/* /target Chiave -a aggiungerà la copia di tutti gli attributi, i permessi e aggiungerà la ricorsività. Quando non è necessaria una riproduzione esatta dei permessi, basta la chiave -r.
Dopo la copia, scopriremo che non tutti i file sono stati copiati: alcuni file che iniziano con un punto sono stati ignorati come:
.profilo
.locale
.mc
e simili.
Perché è successo questo?
Perché i wildcard vengono gestiti dalla shell (bash di norma). Per default, bash ignorerà tutti i file che iniziano con un punto, poiché li interpreta come nascosti. Per evitare questo comportamento, dovremo modificare il comportamento bash utilizzando il comando:
shopt -s dotglob Per mantenere questa modifica del comportamento dopo il riavvio, si può creare un file wildcard.sh con questo comando nella cartella /etc/profile.d (potrebbe esserci una cartella diversa nel tuo distro).
E se nella cartella sorgente non ci sono file, la shell non potrà sostituire nulla al posto dell'asterisco e la copia terminerà con un errore. Per evitare questa situazione ci sono opzioni failglob e nullglob. Dobbiamo impostare failglob, che impedirà l'esecuzione del comando. nullglob non va bene, poiché trasforma la stringa con i wildcard senza corrispondenza in una stringa vuota (di lunghezza zero), il che per cp causerà un errore.
Tuttavia, se ci sono migliaia di file nella cartella, vale la pena rinunciare all'approccio con i wildcard. Il fatto è che bash espande i wildcard in una riga di comando molto lunga simile a:
cp -a /source/a /source/b /source/c …… /targetC'è un limite alla lunghezza della riga di comando che possiamo scoprire usando il comando:
getconf ARG_MAXOttenendo la lunghezza massima della riga di comando in byte:
2097152O:
xargs --show-limitsOtterremo qualcosa come:
….
Lunghezza massima del comando che potremmo effettivamente usare: 2089314
….Quindi, evitiamo di usare del tutto i wildcard.
Scriviamo semplicemente
cp -a /source /target E qui ci imbattiamo in un comportamento ambiguo. cpSe la cartella /target non esiste, otterremo ciò di cui abbiamo bisogno.
Tuttavia, se la cartella target esiste, i file saranno copiati nella cartella /target/source.
Non sempre possiamo rimuovere in anticipo la cartella /target, poiché potrebbero esserci file di cui abbiamo bisogno e il nostro obiettivo, ad esempio, è quello di integrare i file in /target con i file di /source.
Se le cartelle di origine e di destinazione avessero lo stesso nome, per esempio, se copiassimo da /source in /home/source, potremmo utilizzare il comando:
cp -a /source /homeE dopo la copia, i file in /home/source sarebbero stati integrati con i file di /source.
Ecco un rompicapo 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 i file da /source a /target usando cp senza wildcard?
Per superare questa limitazione dannosa utilizziamo una soluzione poco evidente:
cp -a /source/. /targetChi è ben informato su DOS e Linux ha già capito tutto: all'interno di ogni cartella ci sono 2 cartelle invisibili "." e "..", che sono pseudo-cartelle collegate alla directory corrente e alla directory superiore.
- Quando si copia
cpverifica l'esistenza e tenta di creare /target/. - Tale directory esiste ed è /target
- I file da /source sono stati copiati correttamente in /target.
Quindi, appuntiamolo nella nostra memoria o sul muro in grassetto:
cp -a /source/. /target
Il comportamento di questo comando è inequivocabile. Tutto funzionerà senza errori, indipendentemente dal fatto che tu abbia un milione di file o nessuno.
Conclusioni
Se è necessario copiare tutti i file da una cartella all'altra, non utilizziamo wildcard, al loro posto è meglio usare cp in combinazione con un punto alla fine della cartella di origine. Questo copierà tutti i file, compresi quelli nascosti, e non si fermerà con milioni di file o in totale assenza di file.
Postfazione
ha proposto un'opzione equivalente al risultato per il comando:
cp -a -T /source /target
cp -aT /source /target ATTENZIONE: il maiuscolo delle lettere T ha importanza. Se lo mescoli, otterrai un completo disastro: la direzione della copia cambierà.
Ringraziamenti:
- Azienda per il supporto e la possibilità di pubblicare nel proprio blog su Habr.
- Per l'immagine . L'immagine è molto grande e dettagliata, può essere aperta in una finestra separata.
P.S. Invia eventuali errori riscontrati tramite messaggio privato. Accrescerò la karma per questo.
Fonte: habr.com
