Come si spostano i file in blocco in una directory in modo sicuro?


10

Come posso spostare i file in una directory dove potrebbero esserci centinaia o migliaia di file nella directory e potresti non essere sicuro che ci siano duplicati ... Quale metodo useresti?

Il modo in cui gestire i duplicati varierà, a volte sovrascriveremo, a volte dobbiamo essere più sicuri. L'IO può essere importante perché si tratta di server di produzione. Ma data la quantità un prompt per i file non duplicati non è un'opzione. La conservazione delle autorizzazioni, i timestamp, ecc., È importante. Di solito non sappiamo quali siano i dati.

Oh, e non mvè necessario l' utilizzo rsync, cpsoluzioni benvenute.

nota: stiamo eseguendo CentOS 5.5, quindi fatemi sapere se non funzionerà lì perché è una funzione più recente ...


Cosa vorresti fare per i duplicati?

@Iain dipende dalla situazione? Lavoro in un host web ... dipende molto dal mve se ci teniamo alla conservazione nel caso di ... e se abbiamo già fatto un backup. Questa domanda è abbastanza aperta. Sto solo cercando buone opzioni e forse un commento sul fatto che possa mordere o meno e come.
— xenoterracide,

Presumo che ci siano troppi file che la shell può gestire mv * ../o mv -i * ../?
— Michael Mrozek

@Michael Sono sicuro che varia ... in alcuni casi probabilmente no. In alcuni casi forse. Sto cercando di catturare quante più opzioni possibili per il mio ambiente di lavoro.
— xenoterracide,

Risposte:


6

Consiglierei di usare rsync dal genitore:

rsync -avPr -b --suffix='-original' child/* .

che eseguirà il backup di tutti i file duplicati esistenti nel genitore nel file -originale.


Penso che -aimplichi-r
— xenoterracide il

@xenoterracide - Right you 'r'
— Tok

@Tok è possibile fare la copia come hardlink? per non sprecare IO. (come -lper cp)
— xenoterracide,

@xenoterracide: è possibile utilizzare i flag -Ho --hard-linksper rsync per conservare i collegamenti reali .
— Tok

1
@xenoterracide - È possibile utilizzare il --link-dest=DIRflag per ottenere questo comportamento come: rsync -avP --link-dest=/path/to/src /path/to/src/* /path/to/dest/che collegherà duramente in dst / qualsiasi file invariato tra src e src, in questo caso tutti i file. Normalmente vedi questo flag usato quando desideri ricollegare i file di backup senza copiare i loro dati come --link-dest=/most/recent/backup.
— Tok

4
cp -bal . ..

Questo copierà tutto nella directory corrente nella directory sopra di essa, mantenendo tutte le autorizzazioni, usando hardlink per minimizzare IO se possibile, e sui duplicati crea il nome del file ~

dopo di che

rm -rf . ; cd .. ; rmdir <originaldir>;

probabilmente si imbatte in un gran numero di problemi con i file ... ma non è intensivo per IO come rsync.
— xenoterracide,

2

In questo esempio verranno spostati i file da '/ parent / old-dir' a '/ parent':

cd /parent

rsync -av --progress old-dir/ .

rm -rf old-dir

Con le regole rsync sostituirà i duplicati con file più recenti da old-dir.


1

Puoi provare

find . -maxdepth 1 -print0 | xargs -I '{}' -r0 mv '{}' ..

che sovrascriverà i file duplicati in ..

È possibile utilizzare mv -u '{}' per non sovrascrivere se il duplicato in .. è uguale o più recente


perché pipe trova su xargs? perché non usare +
— xenoterracide il

1
@xenoterracide - Abitudine e portabilità (è un'estensione GNU). Inoltre, l'ho appena provato e non riesco a capire come passare il secondo parametro ..al mv '{}' +comando poiché il + si aggiunge alla fine.

@Iain il + è in POSIX Mi è stato effettivamente detto in precedenza GNU find era in ritardo per ottenerlo.
— xenoterracide,

Hai ragione ma non riesco ancora a immaginare un modo per usare il ..

2
@xenoterracide: Con coreutils GNU: -exec mv -t .. -- {} +. Portabile: -exec sh -c 'mv -- "$@"' _ {} +.
— Gilles 'SO- smetti di essere malvagio' il

1

mv -i richiede solo se la destinazione esiste.

yes n | mv -i …sposta tutti i file che non esistono nella directory di destinazione. Su FreeBSD e OSX, puoi accorciarlo a mv -n ….

Si noti che nessuno di questi unirà un argomento di directory con una directory esistente con lo stesso nome nella directory di destinazione.


Un problema a parte è come agire su tutti i file nella directory corrente. Esistono due problemi: afferrare tutti i file ( *omette i file punto) e non eseguire in una riga di comando. Su Linux (o più in generale con GNU find e GNU coreutils):

find . -mindepth 1 -maxdepth 1 -exec mv -i -t .. -- {} +

Con GNU trova ma non coreutils GNU (o coreutils GNU precedenti):

find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -i -- "$@" "$0"' .. {} +

portabile:

find . -name . -o -exec sh -c 'mv -i -- "$@" "$0"' .. {} -type d -prune

Come al solito, zsh semplifica le cose. Non ha una limitazione della lunghezza della riga di comando internamente, quindi se usi il suo mvbuiltin non devi preoccuparti di questo. E puoi dire di non ignorare i file punto con il Dqualificatore glob. Limitazione: non funziona su tutti i filesystem (da zsh 4.3.10).

zmodload zsh/files
mv -i -- *(D) ..

a molti argomenti?
— xenoterracide,

0

Ho detto sul nostro ML

mv * ..

ovviamente questo non è molto sicuro ... sovrascriverà le cose. Potrebbe avere dei limiti che non ho mai incontrato.


2
Se hai un gran numero di file probabilmente otterrai un "errore dell'elenco argomenti troppo lungo".

2
Potrebbe fare cose cattive se hai un nome file che inizia con -. Non rileverà i file il cui nome inizia con ..
— Gilles 'SO- smetti di essere cattivo' il

0

Quello che segue è un modello Python che ho usato con buoni risultati in passato.

#!/usr/bin/env python
#
# Bart Kastermans, www.bartk.nl
#
# rename of collection of files in a directory
import os
import shutil

# only work on files whose name starts with a D
files = [filename for filename in os.listdir ("/Users/kasterma/Music/Audio Hijack/") if filename[0] =="D"]

for filename in files:
    shutil.move (filename, filename [:23] + ".mp3")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.