使用 Linux dd 复制并读取指定位置的文件

使用 Linux dd 复制并读取指定位置的文件

我想使用dd命令将一个文件写入硬盘的任意位置,然后从该位置读取同一个文件。我需要独立于任何文件系统或分区。这似乎并不容易。先决条件是:

  1. 为了做到这一点,我需要能够在硬盘上导航。指南针将是扇区,假设 1 个扇区 = 512 B。
  2. 文件大小假设为 150 B。简单文本文件。
  3. 我想从 2099200 扇区开始写入此文件。

我尝试了这个:

sudo dd if=my.txt of=/dev/sdb obs=512 seek=2099199
sudo dd if=/dev/sdb of=my.txt obs=150 count=1 ibs=512 skip=2099199

但它不起作用,因为我无法让它只读取 150 B,因为计数ibs是 512 B。我需要这个计数才能轻松在硬盘上导航,所以它必须是 512 B。

有没有简单的方法可以处理这种情况dd?或者也许有其他命令或方法可以做到这一点?我需要独立于任何类型的文件系统和分区。

答案1

您可以使用这个来寻求bytes (2099199*512)bs计数。

dd if=your.txt of=/dev/sdb count=1 bs=150 oflag=seek_bytes seek=1074789888 

dd if=/dev/sdb of=your.txt count=1 bs=150 iflag=skip_bytes skip=1074789888 

man dd


那么:

dd if=your.txt of=/dev/sdb bs=1 count=150 seek=1074789888 

dd if=/dev/sdb of=your.txt bs=1 count=150 skip=1074789888 

答案2

初步说明

需要明确的是:

  • 如果您“想从 2099200 扇区开始写入此文件”,则应使用obs=512 seek=2099200。扇区从 0 开始编号。“从扇区 0 开始”可以使用seek=0;“从扇区 1 开始”可以使用seek=1等。
  • 此答案中的命令不包括sudo。这是为了便于阅读。只需sudo在需要时使用即可。

实际答案

我同意,在像你一样写入数据之后,读取时导航的最佳方式是使用ibs=512。当count=1你读取 512 个字节时,obs不能影响这一点。从这 512 个字节中检索出 150 个字节实际上相当容易:

dd if=/dev/sdb ibs=512 skip=2099199 | dd of=my.txt ibs=1 count=150

笔记:

  • 第一个dd不需要count=1。如果它在第二个退出后尝试写入管道dd,它将收到信号(SIGPIPE)并退出。如果您需要第二个dd处理例如 9999 个字节,那么只需count在那里更改就足够了。您不需要count为第一个计算dd。管道机制会让它知道其输出是否丢失了接收器。
  • 另一种方法是… | head -c 150但这不是 POSIX。
  • 一般情况下dd可能会读取部分块,因此我使用了ibs=1 count=150,而不是ibs=150 count=1(比较这个答案)后者将大概在这种情况下,仍然需要记住,dd通常可以读取小于的块,ibs并且每个块仍会增加计数。iflag=fullblock有帮助,但 POSIX 不需要此功能,您dd可能不支持它。第一个dd应该是安全的,尽管ibs=512有两个原因:

    • 输入文件是可寻址的,因此dd只需计算并请求适当的偏移量。如果它从管道读取,则实际上需要读取 2099199 个块,并且通常其中任何一个都可能是部分的,因此丢弃的数据量可能比您预期的要少。可寻址的输入文件在这方面不会带来任何风险。
    • 实际读取一个应该覆盖设备一个逻辑扇区的块时,无法得到部分块。设备要么读取整个扇区,要么什么也不读(读取错误)。请注意,“应该覆盖一个逻辑扇区的块”需要适当的大小偏移量,它不能从扇区的中间开始。 在你的情况下,这些条件是满足的。

改进

tar创建包含两个 512 字节块的档案,其中填充了二进制零作为文件结束标记。这意味着它稍后能够检测到档案的结束位置,可以轻松忽略任何尾随垃圾。此外,它存储元数据(路径、权限等),不限于一个文件,可以存储目录……因此有一些开销,但以下过程似乎很有希望:

档案my.txt

tar -cf my.txt.tar my.txt

将档案写入设备:

dd if=my.txt.tar of=/dev/sdb obs=512 seek=2099199

或者您可以在管道中执行两个步骤,而无需创建my.txt.tar

tar -cf - my.txt | dd of=/dev/sdb obs=512 seek=2099199

(请注意,存档比原始文件大。唯一的文件结束标记将占用 1 KiB。如果所选扇区之后的某处有数据,则应考虑到这一点。my.txt.tar在使用之前,应先创建并将其大小与可用空间进行比较dd。)

无论如何,要检索原始文件,请调用:

dd if=/dev/sdb ibs=512 skip=2099199 | tar -xf -

就是这样。您不需要记住它的大小或名称。您可以tar对通过管道传输到其标准输入的任何档案执行任何操作;例如,您可以列出内容:

dd if=/dev/sdb ibs=512 skip=2099199 | tar -tvf -

相关内容