是否有类似“cp”的命令用于验证数据和删除文件?

是否有类似“cp”的命令用于验证数据和删除文件?

我的手机上有一些照片文件,我正在将它们备份到外部驱动器。 (一切都安装在 Linux 笔记本电脑上。)

我已经复制了这些文件,而我确实应该mv复制它们。

但是,既然我已经这样做了,我想验证每个文件复制的数据是否正确,然后如果文件复制没有错误,则从手机中删除该文件。

所以我真正寻找的是一个cpmv类似的命令:

  • 如果目标上不存在该文件,则复制该文件
  • 验证源和目标之间的数据(复制后,如果文件尚不存在)
  • 如果两个文件的二进制文件相同,则从源中删除该文件

我想我也许可以用 来做到这一点rsync,但我浏览了各种类似删除的选项,但没有一个与“删除来源“,而是这些选项在之前/之后/期间(?)删除文件目的地反而。

答案1

(注意:rsync --remove-source-files这是我正在寻找的命令,只是它不验证数据。)

关于二进制比较,我发现diff可以这样做:

在源目录中:

for f in *.jpg; do diff $f "/path/to/destination/$f"; done

这会比较源和目标上的二进制文件。无输出 = 文件没有差异。

这可用于验证数据。

由于在没有发现差异的情况下diff返回,因此可以这样做0

for f in *.jpg; do diff $f "/desination/$f" && rm $f; done

如果返回,这将删除$f源文件夹中的文件,即;这些文件是相同的二进制文件。diff0

让它看起来像一个新命令可能会很有用,让我们称之为verify-rm

由于我安装了 Dropbox,因此我会将脚本放在 Dropbox 文件夹中,这样当我在 6 个月内重新安装操作系统时,我就不必担心备份它们...

$ cd ~/Dropbox && mkdir my-scripts && cd my-scripts
$ vim verify-rm

这是我的verify-rm脚本:

if [ "$#" -lt 2 ];
then
    echo "Bad arguments, use like cp command"
else
    success=0
    fail=0
    error=0
    for arg in ${@:1:$(($#-1))}
    do
        #echo "$arg ${@:(-1):1}"
        diff "$arg" "${@:(-1):1}"
        ret=$?
        if [ $ret -eq 0 ]
        then
            success=$((success+1))
            echo "Verified file $arg"
            rm $arg
        elif [ $ret -eq 1 ]
        then
            fail=$((fail+1))
            echo "Binary files $arg and ${@:(-1):1} differ"
        else
            error=$((error+1))
            echo "diff exited with error: code=$ret"
        fi
    done
    echo "Summary: $success files verified and ok"
    echo "         $fail files differ!"
    echo "         $error errors"
    echo "Files which differ not removed"
    echo "Files where diff returned error code not removed"
fi

使脚本可执行

$ chmod +x verify-rm

然后使用新脚本(“命令”)

$ verify-rm /path/to/source/*.jpg /path/to/destination

我注意到文件名中带有空格的文件未正确处理,因为 bash 将空格之间的每组字符视为不同的参数。我不知道该怎么办,或者是否可以解决。

然而,评论中指出它rsync --remove-source-files也可以工作,并且rsync当文件名中有空格时可以正常工作,而且我注意到它也快得多,所以我建议只使用rsync.

答案2

您提到了我的评论,rsync --remove-source-files但如果您想进一步了解脚本答案,这里有一些提示:

如果您只想对任何两个文件(包括二进制文件)进行布尔比较,那么有一些比标准diff.其一,对cmp两个文件进行逐字节比较。或者您可以将它们的校验和与例如进行比较,

diff -q <(cksum file1) <(cksum file2)

至于文件名中的空格,这是一个众所周知的问题,有多种可能的解决方案。这是一个非常全面的概要:https://www.dwheeler.com/essays/filenames-in-shell.html。如果您不打算共享您的脚本,只需选择最适合您的工作替代方案即可。

答案3

rsync --remove-source-files将为您完成这个确切的任务。 (但是,我还没弄清楚该怎么做的一件事是,如果目标文件已存在(并且匹配),则删除源文件。)

我发现您的印象是它不验证文件,但根据联机帮助页:

请注意,rsync 始终通过检查文件传输时生成的整个文件校验和来验证每个传输的文件是否在接收端正确重建,但自动传输后验证与此选项的之前无关。 the-transfer “这个文件需要更新吗?”查看。

相关内容