在计算中排除 du/diff 命令中的所有目录和子目录

在计算中排除 du/diff 命令中的所有目录和子目录

我想找出文件中字节的差异。但是,du/diff 命令加上 -a 也会列出目录和子目录。我只想要子目录和目录中的文件,而不是这些。

我知道--exclude选项,但我不知道如何操作它来做到这一点。谢谢。

我的操作系统是 Linux Debian。

我的命令是

dira=/mnt/hdd_a/;
dirb=/mnt/hdd_b/;
diff -u <(cd $dira && du -ab | sort -k2) <(cd $dirb && du -ab | sort -k2)

我也不太理解输出。我认为目录有 + 或 - 的差异是出于多种原因,例如属性。我不关心这个。但是,在数百个文件中,diff 打印出一些没有 + 或 - 的文件。为什么?它们可能在大小以外的其他属性上有所不同?

--- /dev/fd/63  2023-08-22 01:38:15.775099368 +0300
+++ /dev/fd/62  2023-08-22 01:38:15.775099368 +0300
@@ -1,6 +1,6 @@
-364123856483   .
+364123860579   .
 435823780  ./vid_01.mkv
-33781164566    ./news_a
+33781168662    ./news_b
 19110023   ./news_c/covers_09.rar
 161634304  ./news_d/video_d7.avi
 17080320   ./news_e/video_d17.avi

据我了解,“u”选项仅打印 3 行。我想要所有不同的行,而且只打印这 3 行。不打印相同的行(文件大小)。

使用 diff --changed-group-format='%<' --unchanged-group-format='' <(cd "$dira" && du -ab | sort -k2) <(cd "$dirb" && du -ab | sort -k2)

打印一些文件及其大小,没有任何“+/-”指示。所以我不知道差异是来自源文件还是来自目标文件。请注意,目标中缺少整个文件。

答案1

du/diff 命令带有 -a 列表,还列出目录和子目录。我只想要子目录和目录中的文件,而不是这些文件。

我知道--exclude选项,但我不知道如何操作它来做到这一点。谢谢。

如果我理解正确的话,你只想看到所有文件在目录树中,不是任何内容的总大小目录本身。不幸的是,--exclude选项du似乎不支持使用类似的东西/来指示目录,例如du --exclude='*/'仍然会输出目录的大小。

您无需使用命令du本身的任何选项来过滤目录,而是可以使用类似命令find来仅获取文件列表(例如使用其-type f选项),然后将此列表传递给du。该命令在其自己的行上输出每个文件名,我们可以借助find将此文件名列表传递给。该命令要求各个参数由任何空格字符(例如空格、制表符、换行符)分隔,但如果任何文件名包含空格,则不会按我们的预期执行,因此我们改为使用 来指示用 NULL 字符分隔文件名,并使用来指示期望这样的输入:duxargsxargsxargsfind-print0xargs-0

find . -type f -print0 | xargs -0 du -b

我想找出文件中字节的差异。 [...] diff 打印一些没有 + 或 - 的文件。为什么?它们可能除了大小之外在其他属性上有所不同?

为此,您需要直接比较要比较的两个文件的文件大小。该diff命令不执行此操作。相反,diff它用于比较内容两个文件,例如如果文件a.txt包含以下内容......

a
b
c

...文件b.txt包含以下内容...

a
b
d

然后diff a.txt b.txt输出:

3c3
< c
---
> d

这告诉您两个文件之间的差异在于:在第 3 行,删除了a.txt该行( ) 并且添加了该行( )。c<d>

使用diff-u选项会导致其将输出格式化为“统一上下文”补丁文件,如patch命令所用,其风格与其他工具(如 Git)使用的补丁文件类似。也就是说,diff -u a.txt b.txt它会返回以下内容:

--- a.txt   2023-08-22 00:38:07.477617454 +0100
+++ b.txt   2023-08-22 00:38:12.533616240 +0100
@@ -1,3 +1,3 @@
 a
 b
-c
+d

这应该有助于您理解为什么在所运行命令的输出中看到+和。具体来说,输出 的内容大小,按项目名称排序,因此需要两个这样的输出并向您显示这些输出之间的差异。 以 开头的行表示 中存在但不在 中的文件,以 开头的行则相反。-cd $dira && du -ab | sort -k2$diradiff -u <(...) <(...)-$dira$dirb+


该命令不会执行任何更智能的操作,例如直接向您显示和diff中特定文件对之间的文件大小差异。为此,您需要以某种方式指定要比较哪些文件对的大小。$dira$dirb

例如,如果你想比较$dira/news_a和的大小,那么你应该直接比较。如果你只想比较和中文件名为 的$dirb/news_b文件对的大小$dir_a$dir_b一模一样,例如$dir_a/news_a$dir_b/news_a,那么这可以通过编程来完成,如下面的 Bash 脚本所示:

#!/bin/bash

script_location="$( dirname "$(readlink -f "${BASH_SOURCE:-$0}")" )"

dir_a="$1"
dir_b="$2"

cd "$dir_a"
dir_a_filenames="$(find . -type f)"

cd "$script_location"
cd "$dir_b"
dir_b_filenames="$(find . -type f)"

# Combine filename lists
all_filenames="$( sort -u <(echo "$dir_a_filenames") <(echo "$dir_b_filenames") )"

# For each filename in $all_filenames, compare the size of that file in $dir_a with the same file in $dir_b
IFS=$'\n'
cd "$script_location"
for file in $(echo "$all_filenames"); do
    file_a="$dir_a/$file"
    file_b="$dir_b/$file"

    file_a_size="$(if [ -f "$file_a" ]; then stat --format='%s' "$file_a"; else echo 0; fi)"
    file_b_size="$(if [ -f "$file_b" ]; then stat --format='%s' "$file_b"; else echo 0; fi)"
    size_diff=$(($file_b_size - $file_a_size))

    echo -e "$file\tA size = $file_a_size\tB size = $file_b_size\tSize difference = $size_diff"
done

环境$IFS变量定义在循环等结构中使用哪些字符作为项目分隔符for。在这里,我们将其设置为换行符,$'\n'原因与我们之前使用 NULL 分隔符的原因类似xargs

我们使用stat而不是du来获取文件大小,因为这样更快一些,并且我们将不存在的文件的大小视为零,以便报告其大小并计算大小差异;该命令[ -f filename ]用于检查文件是否filename存在。

Bash 语法$((...))用于执行计算,例如$((2+3))输出5;这里我们只是从另一个文件大小中减去一个文件大小。

相关内容