撤消复制(cp)命令操作


14

我通过在终端中使用以下命令行将文件从源文件夹复制到目标文件夹。

sudo cp From_SOURCE/* To_DESTINATION/

现在我要撤消此命令。


我不确定我是否理解。只需删除副本?(sudo rm文件)
Jacob Vlijm 2014年

@JacobVlijm这不是撤消操作,它是一个单独的命令。如果我没有复制,那么我可以在之前使用您建议的命令。而且我已经越来越多的时间使用此命令删除复制的1000多个文件?
αғsнιη

@KasiyA-一个选项是找到所有从中选择的文件名From_SOURCE/*,然后从中删除这些文件名To_DESTINATION/;这可以通过bash来完成-这里的问题可能包括cp命令覆盖了所有内容,复制了符号链接,名称中带有空格的文件等,因此它可能会出现问题并且有点古怪。完美的“撤消”选项可能需要考虑很多东西。
Wilf

Answers:


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
    

警告

如果我很了解您需要实现的目标,请首先尝试测试目录!


如果源目录是“ flat”

如果源目录没有子目录,则脚本甚至可以更简单:

#!/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 2014年

注意:如果源文件中的任何文件都因为名称相同而覆盖了目标文件,则您不能简单地撤消该文件,而此脚本只会删除它。这里的假设是,当您进行初始操作时,没有名称冲突cp
thomasrutter 2014年

@neon_overload正确,在我的答案中对其进行了编辑。
2014年

这不适用于cp -r。我换os.removeprint,它的输出一堆不存在的文件。我假设它缺少子目录,而只在最后列出文件。
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无关紧要。

我将使用的目录名称srcFrom_SOURCEdestTo_DESTINATION

现在,我们的命令是:

cp src/* dest/

如果src包含文件f1f2f3以及目录d1d2,则外壳程序会将命令扩展为:

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,而实际上仍然在同srcdest,现在是/tmp/toDelete/,并且可以在拍摄最后一眼后,被删除。


注意:
(1)检查是否cp为别名cp -i,是否可以通过先询问来防止覆盖文件。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.