Действие команды «Отменить копирование» (cp)

Действие команды «Отменить копирование» (cp)

Я скопировал некоторые файлы из исходной папки в папку назначения, используя следующую командную строку в терминале.

sudo cp From_SOURCE/* To_DESTINATION/

Теперь я хочу отменить эту команду.

решение1

Если я правильно понял, то дело обстоит следующим образом:

  • Вы скопировали (предположительно большое) количество файлов в существующий каталог и хотите отменить действие.
  • Целевой каталог содержит ряддругойфайлы, которые вам нужно там хранить, что делает невозможным их простое удалениевсефайлы из каталога

Скрипт ниже ищет в исходном (исходном) каталоге и перечисляет эти файлы. Затем он ищет в каталоге, в который вы скопировали файлы, и удаляет только перечисленные файлы, поскольку они существуют в исходном каталоге.

Элемент tryдобавлен для предотвращения ошибок, например, в случае, если вы уже удалили некоторые файлы вручную или если не все файлы из исходного каталога были скопированы в место назначения. Если вам нужны привилегии sudo, просто запустите скрипт с помощью "sudo" (см. ниже).

Сценарий

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for root, dirs, files in os.walk(source_dir):
    for name in files:
        try:
            os.remove(target_folder+"/"+name)
        except FileNotFoundError:
            pass

Как использовать

  • Вставьте скрипт в пустой файл, сохраните его как reverse.py,
  • Вставьте правильные пути для исходной и целевой папки,
  • Сделайте его исполняемым для удобства,
  • Запустите его командой:

    [sudo] /path/to/reverse.py
    

Предупреждение

Сначала попробуйте на тестовом каталоге, если я правильно понял, чего вам нужно добиться!


Если исходный каталог «плоский»

Если исходный каталог не имеет подкаталогов, скрипт может быть еще проще:

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for file in os.listdir(source_dir):
    try:
        os.remove(target_folder+"/"+file)
    except FileNotFoundError:
        pass

Примечание

Если копировать действиеперезаписано(заменил) файл с похожим именем в месте назначения, файл будет удален, но исходный файл (конечно) не будет возвращен скриптом. Предполагается, что нет никаких конфликтов имен.

решение2

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или что-то в этом роде, что предотвратило бы перезапись файлов, спросив об этом заранее.

решение3

Это старый вопрос, но я просто хотел опубликовать ответ на чистом bash:

Сначала перейдите в каталог, куда вы скопировали файлы.

cd dest

Затем lsисходный каталог и вывод перенаправляем вrm

ls source | xargs rm

решение4

Это ответ, основанный на временной метке операции копирования. Вы можете перечислить содержимое папки в порядке времени создания и передать его в файл:

ls -alt | file_list

Затем откройте file_listи найдите файлы с той же временной меткой операций копирования. Предположительно, это будут самые последние файлы.

Затем отредактируйте file_listненужные rm -rfфайлы/папки и сохраните.

Затем сделайте следующее:

source file_list

Связанный контент