7

Suppose I have a native (i.e. coming from manufacturers) windows 7 installation on a laptop (with an SSD device, BIOS/MBR partition table if that matters). The partition on the device is completely allocated and dedicated to windows.

I now want to install a linux system alongside windows, and to do that I need to first shrink the windows partition. While I can find ways to do that from within windows or using gparted, how can I do this using only command line programs, like parted or fdisk?

7

GParted is often worth using because it helps avoid several nasty mistakes. I guess the main advantage of command-line tools here is to have more visibility of details. This can be useful in unexpectedly fragile situations (at least once it's broken, the details might help you realize why). However I wouldn't recommend using them to others unless they want to be able to learn from mistakes up to "my disk is now full of zeros and I need to start from scratch".

Also a desktop Linux install process should provide a user-friendly tool for resizing the Windows partition. (Or official documentation). It's the common case. This would be my first recommendation in general.

All of these options will recommend making backups in case of any error.

Confusingly you should not use the parted command-line tool. It used to be a convenient option, but the developers no longer support resizing filesystems with it.


Otherwise, you use ntfsresize, then delete and re-create the partition (fdisk) with the same details except for the size. BEWARE UNITS - SOME TOOLS USE MB; OTHERS MAY SAY MB BUT MEAN MiB. fdisk uses MiB and ntfsresize uses MB. The lazy way is to ntfsresize to much smaller than you need (e.g. 2x), then after recreating the partition you run ntfsresize a second time with no explicit size.

For the hard way, to convert units, you can run numeric expressions in bash. E.g. to see 10GiB in bytes: echo $((10 * 1024 * 1024 * 1024)). You can use those expressions as arguments to command-line tools like ntfsresize.

The partition name for ntfsresize will look like /dev/sda1. lsblk -f will list all partitions (including your boot disc) with their size, and tell you about the filesystem. fdisk will want the name of the disk, like /dev/sda.

For MBR, the partition details to recreate are: partition type and "active"/bootable flag, as well as starting offset.[1] fdisk should show the partition offset in sectors by default. (If not, there may be fractions which are not shown - possibly indicated by a + on the end, but there might be a trap there - you should be sure to always use fdisk in sectors mode).

To avoid typing errors inside fdisk, I sometimes select numbers + paste them with the middle mouse button. That requires either X Windows, or in text mode you need gpm. I think it's less common to provide gpm on the console by default now, but it's there when I use Clonezilla Live. It's convenient, but you could probably lose the number first. So you should probably write the original partition offset down before you delete it.


[1] GPT uses a different format for the type, adds some more flags and a partition UUID. I don't think they'd usually be important; flags wouldn't apply to the main Windows partition and the partition UUID isn't used by much yet.

13

Here comes a memo to resize an NTFS partition using commandline with ntfsresize (from the ntfs-3g / ntfsprogs package) and fdisk, that should work for Windows XP-to-8 versions. Note that GParted does all the following for MBR/DOS as well as for EFI/GPT drives if ntfs-3g / ntfsprogs is installed. My references are at the end.

OK in this scenario I have a MBR-partitionned 149 GB disk with one single NTFS partition (Windows C:). I'll resize it to 20 GB (As @sourcejedi said it well: BEWARE UNITS) in order to make room for new partitions, eg. Data and/or another OS.

Pre-requisite

  • Clean NTFS filesystem: The linux-based NTFS tools will refuse to touch a NTFS filesystem unless it is already perfectly consistent, so as to minimize the chance of data loss. If not, one has to use ntfsfix (from Linux), or chkdsk /f (from Windows).
  • Backup the important data (eg. using ntfsclone as @peterph wrote above)
  • Know which device and partition I want to resize, /dev/sdb1 in this case.

A. Shrink the filesystem

  1. Check the device to ensure it's ready to be resized:

    ~ ntfsresize --check /dev/sdb
    

    Any warning at this point should be addressed before processing further.

  2. Check the size this filesystem can be resized to:

    ~ ntfsresize --info /dev/sdb
    > ...
    > You might resize at 16865632256 bytes or 16866 MB (freeing 112060  MB).
    > ...
    
  3. Test how shrinking to 18 GB will work (we'll make that 20 GiB in a minute):

    ~ ntfsresize --no-action --size 18G /dev/sdb1
    > ...
    > The read-only test run ended successfully.
    
  4. Resize to 18 GB :

    ~ ntfsresize -v --size 18G /dev/sdb1
    > ...
    > Successfully resized NTFS on device '/dev/sdb1'.
    > You can go on to shrink the device for example with Linux fdisk.
    > IMPORTANT: When recreating the partition, make sure that you
    >   1)  create it at the same disk sector (use sector as the unit!)
    >   2)  create it with the same partition type (usually 7, HPFS/NTFS)
    >   3)  do not make it smaller than the new NTFS filesystem size
    >   4)  set the bootable flag for the partition if it existed before
    > Otherwise you won't be able to access NTFS or can't boot from the disk!
    > ...
    

Tip: if the disk has known problems such as bad sectors, add the '--bad-sectors' option.

B. Resize the partition

In the previous step, we shrunk the filesystem, not the partition as we can check with:

~ disktype /dev/sdb

> Block device, size 149.1 GiB (160041885696 bytes)
> DOS/MBR partition map
> Partition 1: 149.1 GiB (138602266624 bytes, 8459611 clusters of 16 KiB, bootable)
> Volume size 18.37 GiB (20799750144 bytes, 1269516 clusters of 16 KiB)

As you can see, the volume size and partition value differ, with Partition 1 still filling the drive. At this stage, it is necessary to delete the partition and create a smaller one to match the new size of the NTFS filesystem. As my disk has a DOS/MBR partition table, I'll do that with fdisk (@peterph has an answer above for GPT):

~ fdisk /dev/sdb
  1. Delete the partition

    Type 'p' to display the partitions on that disk, and note which one contains the resized filesystem.

    Typing ‘d’ will ask which partition you wish to delete

    > Command (m for help): d
    > partition number (1-3, last one by default) : 1
    
  2. Re-create the partition

    Now recreate the partition smaller, keeping it primary and first in order:

    > Command (m for help): n
    > Command action
    > e extended
    > p primary partition (1-4)
    p
    > Partition number (1-4): 1
    > First cylinder (1-31, default 1): 1
    

    Since I shrunk the filesystem to 18GB, let's make the partition 20GiB:

    > Last cylinder or +size or +sizeM or +sizeK (1-31, default 31): +20G
    

    We know the filesystem is NTFS, so use the command action ‘t’ for type and the listed hex code ‘7’ for NTFS:

    > Command (m for help): t
    > Selected partition 1
    > Hex code (type L to list codes): 7
    > Changed system type of partition 1 to 7 (HPFS/NTFS)
    
  3. Next I want to make sure the partition is still marked as bootable:

    > Command (m for help): p
       Device   Boot      Start        End      Blocks   Id   System
    /dev/sdb1               63      40644449  40644387   7  HPFS/NTFS
    

    Make the new partition bootable by adding the boot flag:

    > Command (m for help): a
    > Partition number (1-4): 1
    
  4. Write the altered partition table to disk and exit fdisk with the command action ‘w':

    > Command (m for help): w
    
  5. Now a final resize of the filesystem

    ntfsresize without the 'size' switch will make sure it uses the whole partition's available space (whole of it and no more - thanks @sourcejedi)

    ~ ntfsresize -v /dev/sdb1
    

Now we can check whether the partitions and filesystems on the drive are on pair:

~ disktype /dev/sdb
> ...
> Partition 1: 20.0 GiB (21474836480 bytes, 40644387 sectors from 63, bootable)
> Type 0x07 (HPFS/NTFS)
> Windows NTLDR boot loader
> NTFS file system
> Volume size 19.98 GiB (21453361644 bytes, 1269516 clusters of 16 KiB)

References

  • 2
    Nice demo! You left some margin but only 5%, if you're trying to cover GB/GiB unit error I believe that's around 7%. I also recommended a final resize with no explicit size, to automatically take up the margin - at least it would exclude some future puzzlement. – sourcejedi Jul 27 '15 at 17:11
  • Yeah, adding adding a final ntfsresize with no explicit size would be safer. The damned 7% GB/GiB difference! You're right on both @sourcejedi, thanks! – tuk0z Jul 27 '15 at 20:33
  • i've submitted an edit to put the second ntfsresize after the fdisk write, the other way round didn't make sense. looking great now + upvoted :). – sourcejedi Jul 28 '15 at 9:02
4

You need the ntfsresize utility from the ntfs-3g package, which can resize NTFS file system. However, be sure to backup the partition before you make any changes to it, since sometimes Windows have other ideas of what the resized partition should look like.

The backup can be conveniently performed with the ntfsclone utility (same package), since that saves only the file system (that is the file contents and metadata) and not the whole partition:

ntfsclone -s -o windows-partitinon.img /dev/sdXY

If you are tight on disk space and/or have plenty of time, compressing the image is a good idea:

ntfsclone -s -o - /dev/sdXY | xz -v -9 > windows-partitinon.img.xz

Beware that for moderately full Windows system partition (not much user data), say ~40GB, it can take several hours, depending on the compression level). On the other hand you can as well get to about 40-30% of the uncompressed size.

Apart from that, remember to backup your partition layout to be able to perform full restore. If you are using MBR partition table without any logical partitions, all you need is the MBR of the affected device:

dd if=/dev/sdX bs=512 count=1 of=mbr.sav

If logical partitinos are present, at least save the textual description, e.g.:

fdisk -l -u s /dev/sdX > partitions.sav

For GPT you can use gdisk, which has the ability to save GPT data into a file and then load it back.

Then you can run ntfsresize in write mode. It will likely tell you to reboot to Windows (probably several times), to make sure the changes are registered by the OS.

Only after all this is done, you can resize the partition(s). parted is probably as good as any other partitioning program that understands the partitioning scheme used on that hard drive.

  • I feel the description "resize the partition" omits the important detail of needing to delete the partition and re-create a smaller one. But good point about saving the partition table before that. – sourcejedi Jan 18 '15 at 11:03
  • Personally if you're using fdisk / gdisk for the backup, it'd seem simpler to stick to that for the partition editing as well. In particular parted's print command seems vague about offsets, to verify this sort of work (e.g. for large values it shows the nearest whole GB). Though the rescue command ("rescue a lost [deleted] partition near START and END") seems nice. I'd want to use testdisk for that, but it's nice to know in case you've only got parted. – sourcejedi Jan 18 '15 at 11:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.