Действие команды отмены копирования (cp)


14

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

sudo cp From_SOURCE/* To_DESTINATION/

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


Я не уверен, что понимаю. Просто удалить копию? (файл sudo rm)
Джейкоб Влейм

@JacobVlijm это не отмена действий, это отдельная команда. Если бы я не копировал, я мог бы использовать предложенную вами команду ранее. И мне приходится все больше и больше времени использовать эту команду для удаления более 1000 скопированных файлов?
αғsнιη

@KasiyA - можно найти все выбранные имена файлов From_SOURCE/*и удалить их из To_DESTINATION/; это может быть сделано с помощью bash - проблемы здесь могут быть связаны с тем, что команда cp перезаписывает что-либо, символические ссылки были скопированы, файлы с пробелами в именах и т. д. Идеальный вариант «отменить» мог бы учитывать множество вещей.
Уилф

Ответы:


13

Если я хорошо понимаю, это так:

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

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

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

Заметка

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


Это работает, спасибо. Я управляю им sudo python3 reverse.py. Я принимаю ваш ответ.
αғsнιη

Отлично! Спасибо за хороший вопрос, который описывает ситуацию, в которой мы, вероятно, все были :)
Jacob Vlijm

Примечание. Если какой-либо файл в источнике перезаписал файл в месте назначения из-за того, что он имел то же имя, вы не можете просто отменить его, и этот скрипт просто удалит его. Предполагается, что при инициализации не было ни одного конфликта имен cp.
Томасруттер

@neon_overload Правильно, отредактировал его в моем ответе.
Джейкоб Влейм

Это не работает для cp -r. Я изменил os.removeс print, и он выводит кучу файлов, которые не существуют. Я предполагаю, что в нем отсутствуют подкаталоги, и только список файлов в конце.
Typewar

7

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


5

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

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

cd dest

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

ls source | xargs rm


1
Разбор, lsкак правило, плохая идея. mywiki.wooledge.org/ParsingLs Я не буду опускать ваше сообщение, но оно должно быть отмечено.
Сергей Колодяжный
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.