it-swarm.it

Come sovrascrivere i file di destinazione con mv?

Ho un sacco di file e directory in una sottodirectory che voglio spostare nella directory principale. Esistono già alcuni file e directory nella directory di destinazione che devono essere sovrascritti. I file presenti solo nella destinazione non devono essere toccati. Posso forzare mv a farlo? It (mv * ..) si lamenta

mv: cannot move `xyz' to `../xyz': Directory not empty

Cosa mi sto perdendo?

175
EricSchaefer

Dovrai copiarli nella destinazione e quindi eliminare la fonte, usando i comandi cp -r * .. seguito da rm -rf *.

Non credo che tu possa "unire" le directory usando mv.

128
dogbane

rsync probabilmente sarebbe un'opzione migliore qui. È semplice come rsync -a subdir/ ./.

Il mio albero di prova in filename: contents formato:

./file1:root
./file2:root
./dir/file3:dir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

In esecuzione rsync:

$ rsync -a -v subdir/ ./
sending incremental file list
./
file1
dir/
dir/file3

Dà:

./file1:subdir
./file2:root
./dir/file3:subdir
./dir/file4:dir
./subdir/dir/file3:subdir
./subdir/file1:subdir

E quindi, per emulare mv, probabilmente desideri rimuovere la directory di origine:

$ rm -r subdir/

Dando:

./file1:subdir
./file2:parent
./dir/file3:subdir
./dir/file4:dir

Se questo è sbagliato, puoi fornire un esempio simile (ad esempio usando il mio albero di prova nella parte superiore di questa risposta) con il risultato desiderato?

77
Mikel

rsync può eliminare l'origine dopo le copie con --remove-source-files parametro. Questo dovrebbe essere un modo conveniente per fare ciò che desideri.

Dal rsync man page:

        --remove-source-files   sender removes synchronized files (non-dir)
52
Mike Chen

Puoi farlo con cp e rm, ma senza copiare l'enorme quantità di dati che stai (presumibilmente) stai cercando di evitare il trasferimento. @mattdm ha accennato a questo in il suo commento , e na risposta per un'altra domanda ha una discussione più completa su varie opzioni.

cp -rlf source destination
rm -r source

In sostanza, il -l L'opzione per il comando cp crea collegamenti reali ai file anziché copiare i loro dati in nuovi file.

24
palswim

Ecco uno script che sposta i file da sotto /path/to/source/root al percorso corrispondente in /path/to/destination/root.

  • Se esiste una directory sia nell'origine che nella destinazione, i contenuti vengono spostati e uniti in modo ricorsivo.
  • Se esiste un file o una directory nell'origine ma non nella destinazione, viene spostato.
  • Qualsiasi file o directory già esistente nella destinazione viene lasciato indietro. (In particolare le directory unite vengono lasciate indietro nella fonte. Non è facile da risolvere.)

Attenzione, codice non testato.

export dest='/path/to/destination/root'
cd /path/to/source/root
find . -type d \( -exec sh -c '[ -d "$dest/$0" ]' {} \; -o \
                  -exec sh -c 'mv "$0" "$dest/$0"' {} \; -Prune \) \
    -o -exec sh -c '
        if ! [ -e "$dest/$0" ]; then
          mv -f "$0" "$dest/$0";
        fi
' {} \;

Questa discussione è disponibile da anni e si colloca ancora al primo posto su google, quindi volevo aggiungere un altro metodo. Come faccio di solito questo: comprimendo il contenuto del subdir in un tarball, spostando il tarball nella directory principale e quindi estraendolo con il comportamento predefinito - overwrite. Questo fa esattamente quello che stai cercando. Successivamente puoi rimuovere il tuo sottodir.

cd xyz
tar -cvzpf tmp.tar.gz *
mv tmp.tar.gz ../tmp.tar.gz
cd ..
tar -xvzpf tmp.tar.gz
rm -rf xyz
rm -f tmp.tar.gz
3
Simon Kraus

Se hai abbastanza spazio di archiviazione, puoi farlo nel modo seguente:

mv -bfv directory_1/* directory_2/ # all duplicate source files/directories 
                                   # will have ~ appended to them
find -name "*~" -delete            # will recursively find and delete all files 
                                   # with ~ on the end

Assicurati che non ci siano file importanti con un ~ alla fine di essi, ma se ci sono puoi aggiungere --suffix=whateveryouwant invece del valore predefinito.

0
4D3H2