Скасувати команду дії копіювання (cp)


14

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

sudo cp From_SOURCE/* To_DESTINATION/

Тепер я хочу скасувати цю команду.


Я не впевнений, що розумію. Просто видалити копію? (файл sudo rm)
Яків Влійм

@JacobVlijm це не скасувати дії, це окрема команда. Якщо я не скопіював, я міг би скористатися запропонованою вами командою раніше. І мені доводиться все більше часу використовувати цю команду, щоб видалити понад 1000 файлів, скопійованих?
αғsnιη

@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. Я приймаю вашу відповідь.
αғsnιη

Ідеально! Дякую за приємне запитання, в якому описується ситуація, в якій ми, напевно, всі були :)
Якоб Влійм

Примітка. Якщо будь-який файл у вихідному документі перезаписав файл у пункті призначення, оскільки він мав те саме ім'я, то ви не можете його просто скасувати, і цей сценарій просто видалить його. Припущення тут полягає в тому, що не було зіткнень з іменами, коли ви робили початкові cp.
thomasrutter

@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


2
розбір ls як правило, погана ідея. mywiki.wooledge.org/ParsingLs Я не оскаржую вашу публікацію, але це потрібно зазначити.
Сергій Колодяжний

@SergiyKolodyazhnyy хороший момент. Ніколи не менше: rm `ls`для порожньої заздалегідь порожньої папки та коли файли мають імена без пробілів та нових рядків.
Multifix
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.