You can do it with
losetup, as an alternative to the
dd method described here. Again, this method is dangerous all the same.
Again, the same test file and sizes (remove lines 1-300 from 1000 lines file):
$ seq 1 1000 > 1000lines.txt $ stat +%c 1000lines.txt 3893 # total bytes $ head -n 300 1000lines.txt | wc -b 1092 # first 300 lines bytes $ echo $((3893-1092)) 2801 # target filesize after removal
Create a loop device:
# losetup --find --show 1000lines.txt /dev/loop0 losetup: 1000lines.txt: \ Warning: file does not fit into a 512-byte sector; \ the end of the file will be ignored. # head -n 3 /dev/loop0 1 2 3 # tail -n 3 /dev/loop0 921 922 923
Whoops. There are numbers missing. What's going on?
Loop devices require their backing files to be multiple of sector size. Text files with lines don't usually fit that scheme, so in order to not miss the end of file (last partial sector) content, just append some more data first, then try again:
# head -c 512 /dev/zero >> 1000lines.txt # losetup --find --show 1000lines.txt /dev/loop1 losetup: 1000lines.txt: \ Warning: file does not fit into a 512-byte sector; \ the end of the file will be ignored. # tail -n 3 /dev/loop1 999 1000 \0
The warning persists but the content is complete now, so that's okay.
Create another one, this time with the 300 line offset:
# losetup --find --show --offset=1092 1000lines.txt /dev/loop2 losetup: 1000lines.txt: \ Warning: file does not fit into a 512-byte sector; \ the end of the file will be ignored. # head -n 3 /dev/loop2 301 302 303 # tail -n 3 /dev/loop2 999 1000 \0
Here's the nice thing about loop devices. You don't have to worry about truncating the file by accident. You can also easily verify that your offsets are indeed correct before performing any action.
Finally, just copy it over, from offset device to full:
cp /dev/loop2 /dev/loop1
Dissolve loop devices:
losetup -d /dev/loop2 /dev/loop1 /dev/loop0
losetup -D to dissolve all loop devices.)
Truncate the file to target filesize:
truncate -s 2801 1000lines.txt
$ head -n 3 1000lines.txt 301 302 303 $ tail -n 3 1000lines.txt 998 999 1000