撤消复制 (cp) 命令操作

αғs*_*нιη 14 command-line cp

我通过在终端中使用波纹管命令行将一些文件从源文件夹复制到目标文件夹中。

sudo cp From_SOURCE/* To_DESTINATION/
Run Code Online (Sandbox Code Playgroud)

现在我想撤消这个命令。

Jac*_*ijm 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
Run Code Online (Sandbox Code Playgroud)

如何使用

  • 将脚本粘贴到一个空文件中,另存为reverse.py
  • 为源和目标文件夹插入正确的路径,
  • 为方便起见使其可执行,
  • 通过以下命令运行它:

    [sudo] /path/to/reverse.py
    
    Run Code Online (Sandbox Code Playgroud)

警告

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


如果源目录是“平面”

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

[sudo] /path/to/reverse.py
Run Code Online (Sandbox Code Playgroud)

笔记

如果复制操作覆盖(替换)了目标中的一个类似名称的文件,该文件将被删除,但原始文件(当然)不会被脚本带回。假设不存在名称冲突。


Vol*_*gel 7

特尔;博士:

是存在于所有文件src,并dest可以从被删除dest这样的:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Run Code Online (Sandbox Code Playgroud)

有关分步说明,请参见下文。

简化问题:

要了解我们想要撤消的命令实际上做了什么,我们首先简化它:

我们要撤销的命令是

sudo cp From_SOURCE/* To_DESTINATION/
Run Code Online (Sandbox Code Playgroud)

对于了解如何撤消,sudo是不相关的。

我将使用目录名称srcforFrom_SOURCEdestfor To_DESTINATION

现在,我们的命令是:

cp src/* dest/
Run Code Online (Sandbox Code Playgroud)

如果src包含文件f1, f2and f3, 以及目录d1and d2,shell 将该命令扩展为:

cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
Run Code Online (Sandbox Code Playgroud)

如果没有-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'
Run Code Online (Sandbox Code Playgroud)

这意味着,我们只将简单文件复制到dest.

决定删除哪些文件:

可能存在destsrc. 在这种情况下,文件被覆盖 (1)。对他们来说太晚了,对不起。从最新的备份中取回它们。

关于那里的文件,我们只想删除已复制的文件。这些文件存在于两个目录中,具有相同的名称和相同的内容。

所以我们寻找这些文件:

首先,我们cd进入src,因为它使以下find命令更简单,并设置一个变量为 dest 的绝对路径:

$ cd src
$ destdir="$(readlink -f dest)"
Run Code Online (Sandbox Code Playgroud)

然后,我们列出 src 中的所有文件:

$ find . -maxdepth 1 -type f
Run Code Online (Sandbox Code Playgroud)

并且,对于找到的每个文件,使用cmp检查dest中是否存在内容相同的文件:

$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print
Run Code Online (Sandbox Code Playgroud)

删除文件,小心:

这些文件是我们要删除的文件。但可以肯定的是,我们首先将它们移动到不同的目录中 - 并在运行它们之前查看命令:

$ 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/`
Run Code Online (Sandbox Code Playgroud)

看起来挺好的!现在我们可以省略echo运行真正的mv命令:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;
Run Code Online (Sandbox Code Playgroud)

中的所有文件dest都是从 复制的src,并且在src和 中实际上仍然相同dest,现在在 中/tmp/toDelete/,并且可以在最后查看后将其删除。


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


小智 5

这是旧的,但我只想发布一个纯粹的 bash 答案:

首先切换到复制文件的目录。

cd dest

然后,ls源目录和管道输出到rm

ls source | xargs rm

  • 解析 `ls` 通常是一个坏主意。http://mywiki.wooledge.org/ParsingLs 我不会贬低你的帖子,但必须注意。 (3认同)