Risposte:
mvimpossibile unire o sovrascrivere le directory, fallirà con il messaggio "mv: impossibile spostare" a "in" b ": directory non vuota" , anche quando si utilizza l' --forceopzione.
È possibile aggirare questo utilizzando altri strumenti (come rsync, findo anche cp), ma è necessario considerare con attenzione le implicazioni:
rsyncpuò unire i contenuti di una directory in un'altra (idealmente con l' opzione --remove-source-files1 per eliminare in modo sicuro solo i file di origine che sono stati trasferiti correttamente e con la consueta opzione di autorizzazione / proprietà / conservazione del tempo -ase lo si desidera) rsyncl' --link-dest=DIRopzione (per creare collegamenti fissi invece di copiare il contenuto del file, ove possibile) e --remove-source-filesottenere una semantica molto simile a una normale mv. --link-destdeve essere assegnato un percorso assoluto alla directory di origine (o un percorso relativo dalla destinazione alla fonte ). --link-destin modo non intenzionale (che può o meno causare complicazioni), richiede di conoscere (o determinare) il percorso assoluto verso la fonte (come argomento per --link-dest), e di nuovo lascia una struttura di directory vuota da ripulire come per 1 .find per ricreare in sequenza la struttura della directory di origine sulla destinazione, quindi spostare individualmente i file effettivi cppuò creare collegamenti fissi (semplicemente, puntatori aggiuntivi allo stesso file esistente), che crea un risultato molto simile a una fusione mv(ed è molto efficiente in termini di IO poiché vengono creati solo puntatori e non è necessario copiare dati effettivi) Quale di queste soluzioni alternative (se presenti) è appropriata dipenderà molto dal tuo caso d'uso specifico.
Come sempre, pensa prima di eseguire uno di questi comandi e disponi di backup.
1: Nota che rsync --remove-source-filesnon cancellerai nessuna directory, quindi dovrai fare qualcosa come find -depth -type d -empty -deletedopo per sbarazzarti della struttura della directory dei sorgenti vuota.
mvimplementazione usata da Debian - l'enfasi è stata provata , dato che la manpage non menziona questo comportamento ...
--deleteelimina solo i file nella directory di destinazione che non esistono nella directory di origine.
-Hfisici con la funzione o puoi collegare i file nella destinazione usando --link-dest. Vedi la pagina man prima di usarli, però.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-filesha il vantaggio di rimuovere solo i file che sono stati trasferiti correttamente, quindi è possibile utilizzare findper rimuovere directory vuote e verrà lasciato con tutto ciò che non è stato trasferito senza dover controllare l' rsyncoutput.
È possibile utilizzare l' -lopzione del comando cp , che crea collegamenti reali di file sullo stesso filesystem anziché copie complete. Il comando seguente copia la cartella source/folderin una cartella principale ( destination) che contiene già una directory con il nome folder.
cp -rl source/folder destination
rm -r source/folder
Puoi anche utilizzare il -P( --no-dereference- non rimandare i collegamenti simbolici) o -a( --archive- conservare tutti i metadati, include anche l' -Popzione), a seconda delle tue esigenze.
cppiuttosto che da rsyncquando ogni sistema ha cpe tutti hanno familiarità con esso.
cpcon il tempo di operazione di mv.
-n
mv /fs1/file /fs2/(attraverso i filesystem) eseguirà una copia e quindi una cancellazione.
mvfunzionerà (a condizione che la directory di destinazione non esista ancora) anche se non "in modo efficiente" o come la chiami, cp -rlfallirà.
Consiglierei questi quattro passaggi:
cd ${SOURCE};
find . -type d -exec mkdir -p ${DEST}/\{} \;
find . -type f -exec mv \{} ${DEST}/\{} \;
find . -type d -empty -delete
o meglio ancora, ecco uno script che implementa la semantica simile a mv:
#!/bin/bash
DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"
for SRC in ${@:1:$((${#@} -1))}; do (
cd "$SRC";
find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
find . -type d -empty -delete
) done
rsync -u(aggiorna solo se più recente), mv(almeno in alcune versioni) puoi anche prendere l' -uopzione. Tuttavia, in tal caso, potresti voler eliminare le directory dei sorgenti non vuote e anche quelle vuote, per coprire i casi in cui i file nella struttura dei sorgenti non sono più recenti. @schuess: sembra che ci possano essere più argomenti SOURCE, se ne hai bisogno.
Ecco un modo che unirà le directory. È molto più veloce di rsync dal momento che rinomina i file invece di copiarli e quindi eliminarli.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
destè già una directory con lo stesso nome di in source. E i file verranno spostati in a dest, che è in source. Il comando non fa altro chemv source/* source/dest/.
Un modo per ottenere ciò sarebbe usare:
mv folder/* directory/folder/
rmdir folder
Finché non ci sono due file con lo stesso nome foldere directory/folder, otterrai lo stesso risultato, ovvero l'unione.
rm folder?
rm folder -fRfunziona sempre per me
Per le copie più pure, uso il metodo di copia blockread tar (-) B.
esempio, dal percorso sorgente ('cd' lì se necessario):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
questo crea una copia esatta dell'albero dei sorgenti, con il proprietario e le autorizzazioni intatte. E se esiste la cartella di destinazione, i dati verranno uniti. Solo i file già esistenti verranno sovrascritti.
Esempio:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
Quando l'azione di copia ha esito positivo, è possibile rimuovere l'origine ( rm -rf <source>). Naturalmente questa non è una mossa esatta: i dati verranno copiati, fino a quando non rimuovi la fonte.
Come opzione puoi essere prolisso (visualizza sullo schermo il file da copiare), con -v: tar cBvf -
c: creareB: leggi blocco completo (per pipe letto)v: verbosof: file da scriverex: estratto-: stdout / stdinsourcefolderpuò anche essere *(per qualsiasi cosa nella cartella corrente)
f -di tar non è in genere necessaria: l'impostazione predefinita è leggere da stdin / scrivere a stdout.
Ecco una sceneggiatura che ha funzionato per me. Preferisco mv a rsync, quindi uso le soluzioni di Jewel e Jonathan Mayer.
#!/bin/bash
# usage source1 .. sourceN dest
length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
pushd $SRC;
find . -type d -exec mkdir -p ${DEST}/{} \;
find . -type f -exec mv {} ${DEST}/{} \;
find . -type d -empty -delete
popd
done
Non è una buona idea usare comandi come cp o rsync. Per file di grandi dimensioni, ci vorrà molto tempo. mv è molto più veloce poiché aggiorna solo gli inode senza copiare fisicamente i file. Un'opzione migliore è usare il file manager del tuo sistema operativo. Per Opensuse, esiste un file manager chiamato Konquerer. Può spostare i file senza copiarli. Ha la funzione "taglia e incolla" come in Windows. Basta selezionare tutte le sottodirectory nella directory A. Fare clic con il tasto destro del mouse e "spostarsi" nella directory B che può contenere sottodirectory con gli stessi nomi. Li unirà. Esistono anche opzioni per sovrascrivere o rinominare i file con lo stesso nome.
mvviene utilizzato.
Soluzione Python
Dato che non riuscivo a trovare una soluzione preesistente soddisfacente, ho deciso di creare un rapido script Python per raggiungerlo.
In particolare, questo metodo è efficace perché percorre l'albero dei file di origine solo una volta dal basso verso l'alto.
Ti permetterà anche di modificare rapidamente cose come la gestione della sovrascrittura dei file a tuo piacimento.
Uso:
move-merge-dirs src/ dest/
sposterà tutti i contenuti di src/*in dest/e src/scomparirà.
move-unione-dirs
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
Questo è il comando per spostare file e cartelle in un'altra destinazione:
$ mv /source/path/folder /target/destination/
Ricorda : il mvcomando non funzionerà se la cartella è b̲e̲i̲n̲g m̲e̲r̲ge̲d̲ (cioè un'altra cartella con lo stesso nome esiste già nella destinazione) e il d̲e̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲y .
mv: impossibile spostare "/ sorgente / percorso / cartella" su "/ destinazione / destinazione / cartella": directory non vuota
Se la cartella di destinazione è vuota, il comando sopra funzionerà correttamente.
Quindi, per unire entrambe le cartelle in ogni caso,
fallo in 2 comandi:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
Oppure combina entrambi come comando singolo:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = sposta
cp = copia
rm = rimuovi-r per directory (cartella)
-f forza l'esecuzione
mv. Questa risposta sarebbe migliore con una verità più ampia. Linux, BSD e Unix "reale", o un riferimento da POSIX o SUS.