TL; DR:
Wszystkie pliki, które są obecne w obu src
i dest
można je usunąć w dest
następujący sposób:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Aby uzyskać wyjaśnienie krok po kroku, patrz poniżej.
Uproszczenie problemu:
Aby zrozumieć, co właściwie zrobiliśmy polecenie, zaczynamy od uproszczenia:
Polecenie, które chcemy cofnąć, to
sudo cp From_SOURCE/* To_DESTINATION/
Dla zrozumienia, jak cofnąć, sudo
nie ma znaczenia.
Użyję nazw katalogów src
dla From_SOURCE
i dest
dla To_DESTINATION
.
Teraz naszym poleceniem jest:
cp src/* dest/
Jeśli src
zawiera pliki f1
, f2
a f3
, a katalogi d1
i d2
, powłoka rozszerza tę komendę:
cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
Bez opcji podoba -r
, -R
czy -a
komenda cp
nie kopiuje katalogów.
Oznacza to, że polecenie je pominie, pokazując błąd dla każdego z nich:
$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'
Oznacza to, że skopiowaliśmy tylko proste pliki, a nie katalogi dest
.
Decydowanie, które pliki usunąć:
Możliwe, że były pliki dest
o tej samej nazwie co pliki src
. W tym przypadku pliki zostały nadpisane (1). Przepraszam, jest już dla nich za późno. Odzyskaj je z najnowszej kopii zapasowej.
Jeśli chodzi o pliki, które tam są, chcemy usunąć tylko pliki, które zostały skopiowane. Pliki te istnieją w obu katalogach, o tej samej nazwie i tej samej zawartości.
Szukamy więc tych plików:
Po pierwsze, wchodzimy cd
w to src
, ponieważ find
znacznie upraszcza następujące polecenia i ustawia zmienną na absolutną ścieżkę dest:
$ cd src
$ destdir="$(readlink -f dest)"
Następnie wyświetlamy wszystkie pliki w src:
$ find . -maxdepth 1 -type f
i dla każdego znalezionego pliku użyj, cmp
aby sprawdzić, czy w dest jest plik o tej samej zawartości:
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
Usuwając pliki, ostrożnie:
Te pliki chcemy usunąć. Ale dla pewności najpierw przenosimy je do innego katalogu - i uruchamiamy polecenia przed ich uruchomieniem:
$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/`
mv -n /path/to/dest/./f2 /tmp/toDelete/`
mv -n /path/to/dest/./f3 /tmp/toDelete/`
Wygląda dobrze! Teraz możemy pominąć echo
uruchamianie prawdziwych mv
poleceń:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Wszystkie pliki z dest
tego zostały skopiowane src
i nadal są takie same w src
i dest
są teraz w /tmp/toDelete/
i można je usunąć po ostatnim spojrzeniu.
Uwagi:
(1) Sprawdź, czy cp
jest to alias do, czy coś cp -i
takiego, aby zapobiec zastąpieniu plików, pytając najpierw.