为什么用cp命令复制的目录比原始目录小?


18

我想将一个包含大量文件的目录复制到另一个目的地。我做了:

cp -r src_dir another_destination/

然后,我想确认目标目录的大小与原始目录的大小相同:

du -s src_dir
3782288 src_dir

du -s another_destination/src_dir
3502320 another_destination/src_dir

然后我想到可能有几个符号链接,但cp命令后面没有这些符号链接,而是添加了-a标志:

-a与-pPR选项相同。保留文件的结构和属性,但不保留目录结构。

cp -a src_dir another_destination/

但是du -s给了我同样的结果。有趣的是,源和目标具有相同数量的文件和目录:

tree src_dir | wc -l
    4293

tree another_destination/src_dir | wc -l
    4293

通过du命令获得不同的大小我在做什么错?

更新

当我尝试使用du命令获取单个目录的大小时,会得到不同的结果:

du -s src_dir/sub_dir1
1112    src_dir/sub_dir1

du -s another_destination/src_dir/sub_dir1
1168    another_destination/src_dir/sub_dir1

当我查看带有的文件时ls -la,单个文件的大小是相同的,但总数是不同的:

ls -la src_dir/sub_dir1
total 1168
drwxr-xr-x     5 hirurg103  staff     160 Jan 30 20:58 .
drwxr-xr-x  1109 hirurg103  staff   35488 Jan 30 21:43 ..
-rw-r--r--     1 hirurg103  staff  431953 Jan 30 20:58 file1.pdf
-rw-r--r--     1 hirurg103  staff  126667 Jan 30 20:54 file2.png
-rw-r--r--     1 hirurg103  staff    7386 Jan 30 20:49 file3.png

ls -la another_destination/src_dir/sub_dir1
total 1112
drwxr-xr-x     5 hirurg103  staff     160 Jan 30 20:58 .
drwxr-xr-x  1109 hirurg103  staff   35488 Jan 30 21:43 ..
-rw-r--r--     1 hirurg103  staff  431953 Jan 30 20:58 file1.pdf
-rw-r--r--     1 hirurg103  staff  126667 Jan 30 20:54 file2.png
-rw-r--r--     1 hirurg103  staff    7386 Jan 30 20:49 file3.png

1
有趣的问题。源和目标是否是不同的驱动器,如果这取决于文件系统的块大小,则是否为卷绕机。
大卫

@davidgo,您好,源和目标是同一驱动器上的不同目录。我用ls -la结果更新了问题。看到更新
Hirurg103

2
什么文件系统?目录本身可能比所需的目录更大(占用更多的空间)。比较这个问题。由创建的新目录cp正好与所需的一样大。
卡米尔Maciorowski

使用ls -ls看文件的多少磁盘空间使用。
Barmar

1
递归md5sum是您的朋友,当您需要验证所有文件是否确实被复制并且内容相同时。rsync是另一个可以复制和验证整个结构和文件的工具,如果某些文件已经存在,它也可以加快处理过程。
GoFundMonica-codidact.org

Answers:


21

这是因为du默认情况下不显示文件的大小,而是显示它们正在使用的磁盘空间。您需要使用该-b选项来获取文件大小的总和,而不是所使用的磁盘空间的总和。例如:

% printf test123 > a
% ls -l a
-rw-r--r-- 1 mnalis mnalis 7 Feb  1 19:57 a
% du -h a
4,0K    a
% du -hb a
7       a

即使文件只有7个字节长,它也会占用整个4096字节的磁盘空间(在我的特定示例中;它会根据所使用的文件系统,群集大小等而有所不同)。

此外,某些文件系统支持所谓的稀疏文件,这些文件不使用任何磁盘空间存储全为零的块。例如:

% dd if=/dev/zero of=regular.bin bs=4k count=10
10+0 records in
10+0 records out
40960 bytes (41 kB, 40 KiB) copied, 0,000131003 s, 313 MB/s
% cp --sparse=always regular.bin sparse.bin
% ls -l *.bin
-rw-r--r-- 1 mnalis mnalis 40960 Feb  1 20:04 regular.bin
-rw-r--r-- 1 mnalis mnalis 40960 Feb  1 20:04 sparse.bin
% du -h *.bin
40K     regular.bin
0       sparse.bin
% du -hb *.bin
40960   regular.bin
40960   sparse.bin

简而言之,要验证所有文件均已复制,请使用du -sb代替du -s


1
不仅稀疏文件而且压缩文件和内联文件 / 驻留文件也导致磁盘上的大小变得小于文件大小
phuclv

1
在btrfs / zfs上的结果很奇怪。
瓦尔说莫妮卡

2
@val:BTRFS压缩不影响du输出:这会使压缩文件显得稀疏,而这些程序使用的是通常的算法! btrfs.wiki.kernel.org/index.php/...
彼得·科德斯

@PeterCordes但是CoW的东西使du输出变得毫无意义。
瓦尔说莫妮卡

重复文件呢?现代系统无法通过识别重复内容来节省空间吗?
FreeSoftwareServers

12

这可能是由于目录“文件”的大小所致。

在大多数文件系统中,磁盘上的目录非常类似于常规文件(大多数情况下仅包含名称和节点号列表),并且随着目录的增长使用更多的块。

如果添加许多文件,则目录本身会增长。但是,如果以后再删除它们,则在许多文件系统中,目录将不会收缩。

因此,如果原始树中的目录之一在某个时刻有许多文件,后来又删除了该文件,则该目录的副本将“较小”,因为它仅使用当前文件数量所需的块数。

在更新列表中,有3个目录未列出。比较ls -al输出中那些(或那些后代)的大小。

要找到区别所在,您可以ls -alr在两个目录上尝试一个,然后重定向到文件,然后diff在两个输出中选择一个。


1
好捕获的另一种可能性!但是,如果是OP cp -a src_dir another_destination/,则不太可能(因为它是another_destionation新创建的并因此进行了优化),而src_dir(可能从过去的创建/添加中有一些更大的目录)的确可能会超过所需的大小。但是结果表明src_dir实际上更小(1112 < 1168)。
Matija Nalis

@MatijaNalis只有“更新”之后的第一个示例显示(1112 <1168)...下面的示例反转了数字,并且第一个示例还显示了较大的源(3782288对3502320)。可能是OP的错字?
TripeHound

> In the listings in your update, there are 3 directories you haven't listed。实际上,它们是文件,而不是目录。查看文件名 > if one of the directories in your original tree had many files at some point, which were later deleted。我使用rsync命令从远程服务器复制了源目录,但没有从中删除任何内容
Hirurg103

1
@ Hirurg103 .条目在inode上显示5个链接。一个是从父目录到此目录的链接。另一个是.。还有3个链接,应该是..子目录的链接。除非我缺少一些很奇怪的东西,否则其中必须有3个子目录。您是说那些清单是完整的输出吗?
jcaron
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.