TL; DR:
Усі файли, які є в обох src
і dest
можуть бути видалені з dest
цього вигляду:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Покрокове пояснення див. Нижче.
Спрощення проблеми:
Щоб зрозуміти, що насправді зробила команда, яку ми хочемо скасувати, почнемо, спростивши її:
Команда, яку ми хочемо скасувати, - це
sudo cp From_SOURCE/* To_DESTINATION/
Для розуміння того, як скасувати, sudo
не має значення.
Я буду використовувати імена каталогів src
для From_SOURCE
і dest
для To_DESTINATION
.
Тепер наша команда:
cp src/* dest/
Якщо src
містять файли f1
, f2
і f3
, та каталоги d1
та d2
, оболонка розширює цю команду на:
cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
Без параметрів, таких як -r
, -R
або -a
, команда cp
не копіює каталоги.
Це означає, що команда залишить їх, показуючи помилку для кожного з них:
$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'
Це означає, що ми лише скопіювали прості файли, а не каталоги dest
.
Вибір файлів, які потрібно видалити:
Можливо, там були файли dest
з такою ж назвою, що і файли в src
. У цьому випадку файли були перезаписані (1). Їм вже пізно, вибачте. Поверніть їх із останньої резервної копії.
Щодо файлів, які там є, ми хочемо видалити лише ті файли, які були скопійовані. Ці файли існують в обох каталогах, з однаковим іменем та однаковим вмістом.
Тому ми шукаємо ці файли:
Спочатку ми cd
переходимо до цього src
, оскільки він робить такі find
команди набагато простішими та встановлює змінну на абсолютний шлях dest:
$ cd src
$ destdir="$(readlink -f dest)"
Потім ми перераховуємо всі файли в src:
$ find . -maxdepth 1 -type f
і для кожного знайденого файлу використовуйте, cmp
щоб перевірити, чи є в dest файлі однаковий вміст:
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
Видаліть файли обережно:
Ці файли - ті, які ми хочемо видалити. Але, щоб переконатися, ми спочатку перемістимо їх у інший каталог - і подивимось команди, перш ніж запускати їх:
$ 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/`
Виглядає чудово! Тепер ми можемо залишити echo
для запуску справжні mv
команди:
find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Усі файли dest
, скопійовані з цього файлу src
, і все ще фактично однакові в src
і dest
, зараз є /tmp/toDelete/
, і їх можна видалити після останнього огляду.
Примітки:
(1) Перевірте, чи cp
є псевдонім до того cp -i
чи іншого, що завадило б перезаписати файли, запитавши спочатку.