How to create and format a partition using a bash script?

67

36

Is there any way to create and format a partition using a bash script?

I think it can be done with fdisk but I don't know how to feed commands from the bash script into the fdisk shell then exit the fdisk shell.

I'm wanting to create a partition then format it to ntfs from within bash.

GlassGhost

Posted 2011-09-05T21:38:11.687

Reputation: 919

Answers

72

Similar to the previous suggestions, piping commands to fidsk, I've found this approach useful to leave details for subsequent maintainers. The sed bits strip off all the comments before fdisk gets the input.

# to create the partitions programatically (rather than manually)
# we're going to simulate the manual input to fdisk
# The sed script strips off all the comments so that we can 
# document what we're doing in-line with the actual commands
# Note that a blank line (commented as "defualt" will send a empty
# line terminated with a newline to take the fdisk default.
sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | fdisk ${TGTDEV}
  o # clear the in memory partition table
  n # new partition
  p # primary partition
  1 # partition number 1
    # default - start at beginning of disk 
  +100M # 100 MB boot parttion
  n # new partition
  p # primary partition
  2 # partion number 2
    # default, start immediately after preceding partition
    # default, extend partition to end of disk
  a # make a partition bootable
  1 # bootable partition is partition 1 -- /dev/sda1
  p # print the in-memory partition table
  w # write the partition table
  q # and we're done
EOF

user2070305

Posted 2011-09-05T21:38:11.687

Reputation: 872

3I completely agree. Document your work for others to read. – Eric Duncan – 2015-11-26T13:55:02.200

1Note you have to have a leading tab on each line. – Stu – 2015-12-04T19:06:25.590

2Would you mind placing a big warning that a tab is required on each command character line as @Stu mentioned? I had to debug for a while just because copy-and-paste ignores tabs and replaces them with spaces, thus regex does not match with command lines. – ceremcem – 2016-03-27T01:30:12.327

9Instead of a warning about tabs, I've modified the sed to discard leading whitespace (not just tabs) and not expect a tab after the fdisk commands. This should cut and paste better. @ceremcem - good feedback and sorry to caused you any debug time. – user2070305 – 2016-04-10T15:15:50.327

3sfdisk is more automation friendly than fdisk – spuder – 2017-02-02T17:32:23.887

I used this with success, right up until I happened to place a partition right where one already was, and fdisk wanted confirmation? Then I started using sfdisk which is just way easier and never asks for confirmation. Thanks to Ciro Santilli below. – TaborKelly – 2018-08-15T23:01:59.597

68

sfdisk

sfdisk is a Scripted version of fdisk

It is part of util-linux, just like fdisk, so availability should be the same.

A partition table with a single partition that takes the whole disk can be created with:

echo 'type=83' | sudo sfdisk /dev/sdX

and more complex partition tables are explained below.

To generate an example script, get the setup of one of your disks:

sudo sfdisk -d /dev/sda > sda.sfdisk

Sample output on my Lenovo T430 Windows 7 / Ubuntu dual boot:

label: dos
label-id: 0x7ddcbf7d
device: /dev/sda
unit: sectors

/dev/sda1 : start=        2048, size=     3072000, type=7, bootable
/dev/sda2 : start=     3074048, size=   195430105, type=7
/dev/sda3 : start=   948099072, size=    28672000, type=7
/dev/sda4 : start=   198504446, size=   749594626, type=5
/dev/sda5 : start=   198504448, size=   618891264, type=83
/dev/sda6 : start=   940277760, size=     7821312, type=82
/dev/sda7 : start=   817397760, size=    61437952, type=83
/dev/sda8 : start=   878837760, size=    61437500, type=83

Once you have the script saved to a file, you can apply it to sdX with:

sudo sfdisk /dev/sdX < sda.sfdisk

For sfdisk input, you can just omit the device names, and use lines of type:

start=        2048, size=     3072000, type=7, bootable

They are just ignored if present, and the device name is taken from the command line argument.

Some explanations:

  • header lines: all optional:
  • partition lines:

    • start: offset inside the disk at which the partition starts.

      start has very good defaults, and can often be ommited:

      • on the first line, start is 2048, i.e. 1Mb (2048 + 512), which is a sane default for disk compatibility
      • further start default to the first unallocated position
    • size: man sfdisk says: The default value of size indicates "as much as possible". So to fill the disk with a single partition use: /dev/sda : start=2048, type=83

    • type: magic byte stored on the boot sector for each partition entry. Possible values: https://en.wikipedia.org/wiki/Partition_type On this example we observe:
      • 7 (sda1, 2 and 3): filesystems that Windows supports. Preinstalled Windows stuff and Lenovo recovery partitions. sudo blkid labels help identify them.
      • 5 (sda4): extended primary partition, which will contain other logical partitions (because we can only have 4 primary partitions with MBR)
      • 83(sda5, 7, and 8): partitions which Linux supports. For me one home, and two roots with different Ubuntu versions
      • 82 (sd6): swap

fdisk can also read sfdisk scripts with the I command, which "sources" them during an interactive fdisk session, allowing you further customization before writing the partition.

Tested on Ubuntu 16.04, sfdisk 2.27.1.

Format and populate the partitions an image file without sudo

This is a good way to learn to use sfdisk without blowing up your hard disks: https://stackoverflow.com/questions/10949169/how-to-create-a-multi-partition-sd-disk-image-without-root-privileges/52850819#52850819

Ciro Santilli 新疆改造中心法轮功六四事件

Posted 2011-09-05T21:38:11.687

Reputation: 5 621

4OMG this is amazing. I've used fdisk before but if you accidentally land exactly where there is already a partition it will want verification from the user that it doesn't usually require, which sucks. sfdisk is wonderful, thank you! – TaborKelly – 2018-08-15T22:59:28.337

3This should be the accepted answer – shrewmouse – 2019-02-04T18:59:25.170

56

fdisk reads from stdin so you just need to feed it the appropriate commands. For example, the following clears the partition table, if there is one, and makes a new one that has a single partition that is the; entire disk:

(
echo o # Create a new empty DOS partition table
echo n # Add a new partition
echo p # Primary partition
echo 1 # Partition number
echo   # First sector (Accept default: 1)
echo   # Last sector (Accept default: varies)
echo w # Write changes
) | sudo fdisk

I recommend you do the task you want, recording what you type so you can reproduce it.

e40

Posted 2011-09-05T21:38:11.687

Reputation: 1 143

5While a bit more verbose with the echo commands than the accepted answer, this seems much less magical and obfuscated. – Henry Heikkinen – 2016-11-12T13:05:01.630

1I personally would suggest the use of printf instead of echo just to be in the habit of using something that behaves consistently across systems. – vastlysuperiorman – 2017-07-05T19:22:03.567

@vastlysuperiorman I don't think that printf would work as in-place replacement for echo as it doesn't insert the line break – Andrey – 2019-12-12T17:41:49.057

@Andrey you are correct. The equivalent of echo o here would be printf "o\n" which looks less clean. I personally prefer printf because it feels more intentional, but echo is a totally valid solution. – vastlysuperiorman – 2019-12-12T18:09:41.523

37

You can do it with just a couple of commands, use intros \n instead of multiple echos.

echo -e "o\nn\np\n1\n\n\nw" | fdisk /dev/sda

kikeenrique

Posted 2011-09-05T21:38:11.687

Reputation: 549

This is more terse than the others, but unfortunately seems to only work with bash. – bk138 – 2015-02-09T18:34:45.043

It's working with ash/busybox too. – kikeenrique – 2015-02-10T08:59:36.847

There are, however, problems with dash :-/ – bk138 – 2015-02-11T15:01:17.373

2Is another \n needed after the w? – Qian Chen – 2015-07-17T13:48:20.780

6This works, but is horrible :-) – Ciro Santilli 新疆改造中心法轮功六四事件 – 2015-09-09T13:23:52.820

2@ElgsQianChen: no, because echo automatically terminates the line with a newline (unless -n option is used) – Udo G – 2015-11-09T08:14:27.360

would printf work better? i vaguely remember seeing somewhere that printf is the preferred method for some types of output. my understanding is there are 2 versions of echo: one in the shell; one as a command line version (i.e. stored in /bin/ in my linux dist) – northern-bradley – 2017-10-23T05:01:35.780

I had to add another \n, so this worked for me: echo -e "o\nn\np\n1\n\n\nw" | fdisk /dev/sdb – Mendhak – 2017-10-30T11:46:26.907

5

Create a new disklabel type gpt:

sudo /sbin/parted /dev/xvdf mklabel gpt --script

Partition the disk:

sudo /sbin/parted /dev/xvdf mkpart primary 0% 100% --script

Bruce Davis

Posted 2011-09-05T21:38:11.687

Reputation: 51

Thank you, this is the only clean solution for me cause it dosn't include piping some kind of "space opera.docx" to fdisk. – Benibr – 2018-03-07T14:52:05.890

5

You can script fdisk.

(echo n; echo p; echo 1; echo 1; echo 200; echo w) | fdisk /dev/sdc

That creates a 200 MB partition on /dev/sdc

ron

Posted 2011-09-05T21:38:11.687

Reputation: 51

Elegant answer! – Gangadhar Jannu – 2018-03-20T08:45:56.420

5

Piping commands to fdisk works well as explained by other people, but this way a bit more elegant and readable:

fdisk /dev/sdc <<EOF
n
p
1


w
EOF

Piping from a (temporary) file also works:

fdisk /dev/sdc < /tmp/fdisk.cmds

Ray

Posted 2011-09-05T21:38:11.687

Reputation: 249

This one gets my vote. It's clean and isn't polluted with a running commentary. – David Betz – 2016-08-08T15:25:39.483

1

printf 'o\nn\np\n1\n\n\nw' | fdisk /dev/sda

Diego Roberto Dos Santos

Posted 2011-09-05T21:38:11.687

Reputation: 129

2

A common mistake new users make is to answer without details of how to actually resolves the issue. Answers should be detailed and include references, as needed. Please take a few minutes to edit your answer to include details of why your answer is valid. If you need some help, read How do I write a good answer?. Also, please realize you have posted an answer to a very old questions which has an accepted answer. Although there is noting wrong with doing so, you may not get a response from the OP.

– CharlieRB – 2016-03-23T19:49:17.770

1

Is this different from: http://superuser.com/a/739586/128124 ?

– Ciro Santilli 新疆改造中心法轮功六四事件 – 2016-10-08T14:22:19.073

0

The script uses fdisk to create partitons based on other people answers.

Change the following in the script:

NUM_PARTITIONS=5

PARTITION_SIZE="+10G"

Example usage is given after the script.

#!/bin/bash
if [ $# -eq 0 ]
then
  echo "input the device"
  exit
fi

NUM_PARTITIONS=5
PARTITION_SIZE="+10G"    

SED_STRING="o"
TAIL="p
w
q
"

NEW_LINE="
"
LETTER_n="n"
EXTENDED_PART_NUM=4
TGTDEV=$1

SED_STRING="$SED_STRING$NEW_LINE"
for i in $(seq $NUM_PARTITIONS)
do
  if [ $i -lt $EXTENDED_PART_NUM ]
  then
    SED_STRING="$SED_STRING$LETTER_n$NEW_LINE$NEW_LINE$NEW_LINE$NEW_LINE$PARTITION_SIZE$NEW_LINE"
  fi
  if [ $i -eq $EXTENDED_PART_NUM ]
  then
    SED_STRING="$SED_STRING$LETTER_n$NEW_LINE$NEW_LINE$NEW_LINE$NEW_LINE"
    SED_STRING="$SED_STRING$LETTER_n$NEW_LINE$NEW_LINE$PARTITION_SIZE$NEW_LINE"
  fi
  if [ $i -gt $EXTENDED_PART_NUM ]
  then
    SED_STRING="$SED_STRING$LETTER_n$NEW_LINE$NEW_LINE$PARTITION_SIZE$NEW_LINE"
  fi
done
SED_STRING="$SED_STRING$TAIL"

sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | fdisk ${TGTDEV}
  $SED_STRING
EOF

run with:

sudo sh mk_partition.sh /dev/sdxxx

Paul Justin

Posted 2011-09-05T21:38:11.687

Reputation: 1

-2

#!/bin/sh
hdd="/dev/hda /dev/hdb /dev/hdc"
for i in $hdd;do
echo "n
p
1


w
"|fdisk $i;mkfs.ext3 "$i1";done 

You can use this script. Just make sure you define your own partitions where hdd is defined. There are 2 blank spaces between 1 and w; they need to be there for taking default values.

Shailesh Sutar

Posted 2011-09-05T21:38:11.687

Reputation: 99