it-swarm-eu.dev

Jak přepsat cílové soubory pomocí mv?

Mám spoustu souborů a adresářů v podadresáři, který chci přesunout do nadřazeného adresáře. V cílovém adresáři již jsou některé soubory a adresáře, které je třeba přepsat. Soubory, které jsou přítomny pouze v cíli, by neměly zůstat nedotčeny. Mohu k tomu donutit mv? To (mv * ..) stěžuje si

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

Co mi chybí?

175
EricSchaefer

Budete je muset zkopírovat do cíle a poté smazat zdroj pomocí příkazů cp -r * .. následován rm -rf *.

Nemyslím si, že můžete "sloučit" adresáře pomocí mv.

128
dogbane

rsync by zde pravděpodobně byla lepší volba. Je to tak jednoduché jako rsync -a subdir/ ./.

Můj testovací strom ve formátu filename: contents:

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

Spuštění rsync:

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

Dává:

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

A pak, pokud chcete emulovat mv, pravděpodobně budete chtít odstranit zdrojový adresář:

$ rm -r subdir/

Dává:

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

Pokud to není správné, můžete uvést podobný příklad (např. Použít můj testovací strom z horní části této odpovědi) s požadovaným výsledkem?

77
Mikel

rsync může smazat zdroj po kopiích pomocí --remove-source-files parametr. To by měl být pohodlný způsob, jak dělat to, co chcete.

Z rsync man page:

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

Můžete to provést pomocí cp a rm, ale bez kopírování obrovského množství dat, která se (pravděpodobně) snažíte zabránit přenosu. @mattdm to zmiňoval v jeho komentář a odpověď na jinou otázk má úplnější diskusi o různých možnostech.

cp -rlf source destination
rm -r source

Možnost -l Pro příkaz cp v podstatě vytváří pevné odkazy na soubory, nikoli kopírování jejich dat do nových souborů.

24
palswim

Zde je skript, který přesouvá soubory pod /path/to/source/root na odpovídající cestu pod /path/to/destination/root.

  • Pokud adresář existuje jak ve zdroji, tak v cílovém adresáři, bude obsah rekurzivně přesunut a sloučen.
  • Pokud soubor nebo adresář existuje ve zdroji, ale ne v cílovém umístění, bude přesunut.
  • Jakýkoli soubor nebo adresář, který již v cíli existuje, zůstane pozadu. (Zejména sloučené adresáře jsou ve zdroji pozadu. Není snadné je opravit.)

Dejte si pozor, netestovaný kód.

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
' {} \;

Toto vlákno je tam roky a stále se řadí na 1. místo na google, takže jsem chtěl přidat další metodu. Jak to obvykle dělám: zabalení subdirového obsahu do tarballu, přesunutí tarballu do nadřazeného adresáře a jeho extrahování pomocí výchozího chování - overwrite. To dělá přesně to, co hledáte. Poté můžete odstranit své subdir.

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

Pokud máte dostatek úložiště, můžete to udělat následujícím způsobem:

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

Ujistěte se, že na konci nejsou žádné důležité soubory, ale pokud ano, můžete přidat --suffix=whateveryouwant místo výchozí.

0
4D3H2