2

I have a partition, say 190 GB, followed by 100 GB of unpartitioned disk free space.

I want to move this partition 100GB "to the right" (towards a higher sector number), so that the free unpartitioned free space would then be on the left of it.

This partition cannot just be copied carelessly, because:

  • it contains encrypted data that must be preserved (on the block level),
  • there is an overlap between the old and new position of the partition.

I know GParted should be able to handle this. However I would like to do it myself with command line tools. I know sfdisk has something like this to move partition 100M to the right:

echo '+100M,' | sfdisk --move-data /dev/sdc -N 1

I'd like to know 2 things:

  • If I was to move data manually, using tools like dd (or others), how would I do that? I believe the end of the partition must be copied before the start of it, like a backward read-and-copy (of course, I would also need to edit the GPT partition table).
  • If I want to use sfdisk, how can I use it so that I shift by a very precise sector number, so that it properly "touches" the partition that is on the far end of the disk? (so that they are really next to each other with no gap in between)
7
  • dd is not the right tool for this. You would have to manually make sure the partition sizes are correct before and after the copy and that the partition tables match what your just dd'ed to the raw disk. If sfdisk does what you want and their commands have been vetted, go with an accepted tool.
    – doneal24
    Apr 26, 2023 at 1:19
  • Side note: you say "move partition", but you want to move the partition and the filesystem within it. Windows often pretends partitions are filesystems, in Linux we should know better. Moving a partition is fast and easy, all you need to do is to update the partition table. If there was no filesystem (yet or at all) inside the partition, there would be no problem. Moving the existing filesystem to match the new partition is the non-trivial task your question is about. Thus I say the title should be "move a partition with filesystem…" or so. Apr 26, 2023 at 3:16
  • @KamilMaciorowski Yes, the partition contains encrypted data that must be preserved, I edited my question.
    – Totor
    Apr 26, 2023 at 8:05
  • @doneal24 so, what is the right tool then? dd can work pretty well for moving a partition "backwards" (as it reads forward by default)
    – Totor
    Apr 26, 2023 at 13:45
  • Probably GNU ddrescue with --reverse and --max-read-errors=0 can be (ab)used. It won't be as straightforward as sfdisk --move-data, but if you overcome few obstacles and set all the relevant parameters right then one invocation of ddrescue will do the job. So it's not as "manually" as with dd, where you need to run a loop and calculate offsets in each iteration. Note you should only ask practical, answerable questions based on actual problems that you face. "If I was…?" does not fit. "I don't have sfdisk …" may fit if it's true. Apr 27, 2023 at 6:03

1 Answer 1

1

If I want to use sfdisk, how can I use it so that I shift by a very precise sector number, so that it properly "touches" the partition that is on the far end of the disk? (so that they are really next to each other with no gap in between)

You do that by providing the number of sectors as input to sfdisk:

echo '+NUM' | sfdisk --move-data /dev/sdc -N 1

will move the 1st partition NUM sectors to the right.
As explained in the manual

A numerical argument is by default interpreted as a number of sectors

Only when NUM is followed by a multiplicative suffix (like M, KiB etc) will sfdisk treat it as a size in bytes (e.g. +50GiB).


How do you know the number of sectors? Simple, sfdisk will report it via the -F switch:

-F, --list-free [device...]
List the free unpartitioned areas on all or the specified devices.

Sample output (I marked the no. of sectors of the free area in bold):

    Start       End    Sectors   Size
114369428 324084628  209715200   100G

so using that number as NUM in the first command:

echo '+209715200' | sfdisk --move-data /dev/sdc -N 1

will move the 1st partition next to the following one with no gap in between.


For the record, here it is in action on a 2GB sd-card (non-relevant parts of output removed):
There were 4 partitions, I deleted the 3rd one, so as to have free space following the 2nd partition that I will then move next to last partition. I start by listing the existing partitions:

sfdisk -l /dev/sdc  

[...]

Device    Boot   Start     End Sectors  Size Id Type
/dev/sdc1         2048 2099199 2097152    1G  c W95 FAT32 (LBA)
/dev/sdc2      2099200 2488319  389120  190M  c W95 FAT32 (LBA)
/dev/sdc4      2693120 3966975 1273856  622M  7 HPFS/NTFS/exFAT

Partition sdc2, that I want to move, ends at sector 2488319, so the free space starts at sector 2488320. I then list free space areas:

sfdisk -F /dev/sdc

Unpartitioned space /dev/sdc: 101,5 MiB, 106430464 bytes, 207872 sectors
[...]

  Start     End Sectors  Size
2488320 2693119  204800  100M
3966976 3970047    3072  1,5M

There are two free space areas - I need the no. of sectors for the one that starts at 2488320... I then use that number - 204800 - as input to sfdisk to move partition no.2:

echo '+204800' | sfdisk /dev/sdc  -N 2 --move-data
Checking that no-one is using this disk right now ... OK

[...]

Old situation:

Device    Boot   Start     End Sectors  Size Id Type
/dev/sdc1         2048 2099199 2097152    1G  c W95 FAT32 (LBA)
/dev/sdc2      2099200 2488319  389120  190M  c W95 FAT32 (LBA)
/dev/sdc4      2693120 3966975 1273856  622M  7 HPFS/NTFS/exFAT

New situation:

Device    Boot   Start     End Sectors  Size Id Type
/dev/sdc1         2048 2099199 2097152    1G  c W95 FAT32 (LBA)
/dev/sdc2      2304000 2693119  389120  190M  c W95 FAT32 (LBA)
/dev/sdc4      2693120 3966975 1273856  622M  7 HPFS/NTFS/exFAT

Data move:
  start sector: (from/to) 2099200 / 2304000
  sectors: 389120
  step size: 1048576 bytes

Moved 389120 from 389120 sectors (100%).

The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Per the New situation: output, partition 2 end sector is now 2693119 and partition 4 start sector is 2693120, i.e. no gap in between.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .