Currently, I mainly use Ubuntu and MacOS. Furthermore, I also get in contact with Windows from time to time. To transfer data between machines running these different operating systems I use a USB flash drive. Unfortunately, many USB flash drives don't work under Linux, Windows and MacOS at the same time out of the box. For instance, a while ago I experienced that my USB flash drive works normally under Linux and Windows, but under MacOS I only had read access but no write access. This behavior is caused by the fact that many USB flash drives are formatted using the NTFS file system.

Note: A file system is responsible for organizing a drive. For instance, it specifies how the data is stored or how file permission is handled.

NTFS is the file system Windows likes to use by default nowadays. However, NTFS doesn't work properly under MacOS. There are a few alternatives to NTFS. You can read more about them here. I was looking for a file system that works under Linux, Windows and MacOS. The exFat file system meets this requirement. In the following I want to describe how I formatted my USB flash drive as exFat on Ubuntu 18.04 LTS. To do so I actually followed a great tutorial written by Kevin Arrows. In the following I will summarize it in my own words. However, if you prefer to read the original tutorial, you can find it here.

Note: If you want to format your USB flash drive as exFat under Windows, you can check out this tutorial. If you want to do it under MacOS, you can have a look here. However, I can’t guarantee that these tutorials actually work, since I haven’t tested them myself.

Warning: If you have additional requirements besides that the USB flash drive should work under Linux, Windows and MacOS, you might want to consider other file systems as well. You can find additional information about which file system to use here and here.

Important: (Update) Below I describe a way how to format a portable drive as exFat that was supposed to work under Linux, Windows and MacOS. Unfortunately, after I posted the first verison of this blog post I found out that it actually only works on Linux and MacOS but not Windows. That’s why I added an additional section ExFat on Windows (see below) later, that describes a way to format the drive as exFat which also works under Windows. If this is what you are looking for, you may want to scroll down to this section already and skip my first solution that only works on Linux and MacOS. If you only want to use the drive on Linux and MacOS on the other hand or if you want to get some additional information, you can keep reading from here.

First of all, we need to install the exFat drivers on Ubuntu.

sudo apt-get install exfat-fuse exfat-utils

Then, we can plug in the USB flash drive into our machine. It should be automatically recognized and mounted by Ubuntu. You should see an icon on your desktop that represents your USB flash drive. Alternatively, you should also be able to find your mounted USB flash drive under /media using your terminal (other Linux distributions usually mount it under /mnt).

Next, we need to find out the name of our drive. We can use fdisk for this.

sudo fdisk -l

The command above should print a list of devices that are attached to our system. Pay very close attention to find the right drive name, since we are going to erase all data of that drive later.

Warning: Pay very close attention to find the right drive name, since we are going to erase all data stored on the drive! For instance, if you find a drive named /dev/sda (or something similar) in the device list, you must not choose this one! The drive /dev/sda is usually the drive that is used to boot GNU/Linux from. It is not your USB flash drive. You don’t want to format it!

Often times our USB flash drive will show up as /dev/sdb in the device list. When I ran fdisk -l, the /dev/sdb entry showed up like this in the device list.

Disk /dev/sdb: 14,5 GiB, 15518924800 bytes, 30310400 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7dffaefd

Device  Boot Start      End  Sectors  Size Id Type
/dev/sdb1       2048 30310399 30308352 14,5G 86 NTFS volume set

You can also check if the total memory that is displayed for /dev/sdb matches your USB flash drive's memory. On my USB flash drive it is written that it has 16 GB of storage. In the device list /dev/sdb shows 14.5 GB which is not exactly 16 GB, but it comes closest among all devices in the device list. Hence, /dev/sdb must be our USB flash drive (here you can read more about why it doesn't show up as exactly 16 GB). But wait! We actually see /dev/sdb and /dev/sdb1 here. What do both mean? Well, /dev/sdb is the name of our drive, whereas /dev/sdb1 is the name of the partition on our drive.

Note: A drive is usually divided into multiple sections, which we call partitions. This way we can separate the files that are stored on the drive in a certain way. For instance, usually the internal disk drive of our machine holds all operating system related files in one partition and all data files (e.g. photos, documents) in another partition. This often makes sense, because then we are able to format the partition holding our operating system to replace it with a newer one while keeping our data on the other partition untouched. However, in contrast to our internal disk drive our USB flash drive can often be simply organized as one big partition, since we only store our personal data there. When we run sudo fdisk -l on Ubuntu, all devices attached to our machine get listed. Usually our USB flash drive has the name /dev/sdb here. Each of its partitions is listed with a number attached to that name, e.g. /dev/sdb1, /dev/sdb2 etc. If our USB flash drive has just one partition, we will only find /dev/sdb1 in the device list.

In the following I'm going to assume that /dev/sdb is the correct name of our drive. However, you should still double-check, if this is also the correct name of your drive on your system! Furthermore, make sure there isn't any data on the drive that you still need, since we are going to format the drive now.

Warning: Make sure that you don’t have any data on the USB flash drive anymore that you still need. If there is still data on the drive that you still need, you have to make a backup of the data before you proceed.

Next, we want to delete the current filesystem of our USB flash drive to start with a fresh file system. To do that we need to unmount our drive first.

sudo umount /dev/sdb*

We should either get no output or the following output. No error should appear.

umount: /dev/sdb: not mounted.
umount: /dev/sdb1: not mounted.

The icon on the desktop representing our USB flash drive should disappear and also under /media it shouldn't be mounted anymore (or /mnt on other Linux distributions). Now we can delete the file system. To do this we can use a tool called wipefs.

sudo  wipefs -a /dev/sdb

We should get the following (or similar) output.

/dev/sdb: 2 bytes were erased at offset 0x000001fe (dos): 55 aa
/dev/sdb: calling ioctl to re-read partition table: Success

Note: wipefs actually doesn’t remove the filesystem itself or any other data on the drive but the filesystem’s signature. However, this is enough to be able to set up a new file system on the drive. You can read more about wipefs here. If you also want to immediately erase all data on your drive, check out this article.

Next, we need to create a new partition table. We can use fdisk for this.

sudo fdisk /dev/sdb

Note: A partition table describes all partitions of the drive.

We should get the following output.

Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xa8df2b81.

Command (m for help):

As we can see, a command prompt appeared. We need to type n and then Enter to create our partition. Then, we are asked to specify a few parameters that are needed to create the partition on our drive: a) what partition type we want, b) how many partitions should be created and c) from which to which sector on the drive should each partition go. Since we simply want a single partition on our USB flash drive that encompasses the whole drive space, we can use the default values that are provided to us here.

Welcome to fdisk (util-linux 2.31.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xa8df2b81.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-30310399, default 2048): 2048
Last sector, +sectors or +size{K,M,G,T,P} (2048-30310399, default 30310399): 30310399

Created a new partition 1 of type 'Linux' and of size 14,5 GiB.

Command (m for help):

However, as you can see there is still one problem here. The type of the created partition is Linux, which will make it difficult to use our USB flash drive on Windows and MacOS. We need to change the type! We can change the partition type with the fdisk command t. After hitting Enter we are asked to provide the hex code of the desired partition type. We can list all available types by typing L. In the upcoming list we should look for HPFS/NTFS/exFAT and take its hex code. Usually it will have the number 7. So, let's type 7 to change the type of our partition from Linux to HPFS/NTFS/exFAT.

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): 7
Changed type of partition 'Linux' to 'HPFS/NTFS/exFAT'.

Command (m for help):

Important: Sometimes fdisk also asks you to remove a signature from the drive. Unfortunately, I haven’t really understood yet what this signature is used for. Is it the file system’s signature that should already been removed by wipefs? Well, I simply agreed to remove this signature as well. My USB flash drive still worked as expected after formatting. However, if your USB flash drive is extremely important to you, you might want to further investigate about this signature before you proceed.

Finally, we can execute all of our commands by typing w and Enter. Depending on how large your drive is, it might take a few seconds. We should see the following output.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

After creating the partition and the partition table, we can finally create the file system. We can do this with the following command.

sudo mkfs.exfat -n bam098 /dev/sdb1

bam098 is just the name that I decided to give my USB flash drive. You can use any name you like here. After running the command we should see the following or a similar output (the mkexfatfs version might differ on your system).

mkexfatfs 1.2.8
Creating... done.
Flushing... done.
File system created successfully.

To check if there are any errors we can also run the following.

sudo fsck.exfat /dev/sdb1

We should see the following or a similar output.

exfatfsck 1.2.8
Checking file system on /dev/sdb1.
File system version         1.0
Sector size                 512 bytes
Cluster size                32 KB
Volume size                 14 GB
Used space                  2 MB
Available space             14 GB
Totally 0 directories and 0 files.
File system checking finished. No errors found.

We should make sure that it says No errors found. Finally, I tested my USB flash drive, formatted with exFat as described above, on my Ubuntu 18.04 LTS and a machine running MacOS Catalina. It worked on both systems.

ExFat on Windows (Update)

After I wrote this blog post I was able to test my USB flash drive, formatted with exFat as described above, also on a machine running Windows 10. Unfortunately, I didn't work to my surprise. I'm not really sure why it doesn't work, but on askubuntu.com I found another solution to format a USB flash drive as exFat, which does also work under Windows 10. In the following I want to describe the whole process again (on my Ubuntu 18.04 LTS) using this new solution.

If you haven't done so, you should install the exFat drivers on your Ubuntu.

sudo apt-get install exfat-fuse exfat-utils

Then, we need to plug our USB flash drive into our machine. It should be automatically recognized and mounted by Ubuntu. Again, an icon representing our USB flash drive should appear on the desktop. Alternatively, we should also find it under /media using the terminal (usually under /mnt on other Linux distributions).

Next, we need to find out the name of our drive. We can use fdisk for this as before.

sudo fdisk -l

As described above, the command should print a list of devices that are attached to our system. Pay very close attention to find the right drive name, since we are going to erase all data of that drive later. In the following let's assume again that our USB flash drive shows up as /dev/sdb in the device list and /dev/sdb1 indicates its first (and usually only) partition. When I ran the command, it showed up as follows.

Disk /dev/sdb: 14,4 GiB, 15476981760 bytes, 30228480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x36345114

Device     Boot Start      End  Sectors  Size Id Type
/dev/sdb1        2048 30228479 30226432 14,4G  7 HPFS/NTFS/exFAT

Again, you can check if the total memory that is displayed for /dev/sdb matches your USB flash drive's memory. As described above it will most likely be a little less as advertised on your USB flash drive. If you want to read again why that is, please see above.

Besides fdisk there are also other tools to find out the device name. One of them is lsblk for instance.

lsblk

It should also print a device list and our USB flash drive should appear as /dev/sdb in the following way.

sdb                       8:16   1  14,4G  0 disk  
└─sdb1                    8:17   1  14,4G  0 part 

Warning: Pay very close attention to find the right drive name, since we are going to erase all data stored on the drive! For instance, if you find a drive named /dev/sda (or something similar) in the device list, you must not choose this one! The drive /dev/sda is usually the drive that is used to boot GNU/Linux from. It is not your USB flash drive. You don’t want to format it! The correct drive could be /dev/sdb as in my example here but it doesn’t have to be the correct one on your system.

Next, we need to unmount our drive.

sudo umount /dev/sdb*

We should either get no output or the following output. No error should appear.

umount: /dev/sdb: not mounted.
umount: /dev/sdb1: not mounted.

The icon on the desktop representing our USB flash drive should disappear and it should also not be mounted under /media (or /mnt on other Linux distributions) anymore. Additionally, we can also check with df whether /dev/sdb is still mounted.

df

df prints a list of mounted devices which shouldn't contain /dev/sdb* anymore.

Warning: Make sure that you don’t have any data on the USB flash drive anymore that you still need. If there is still data on the drive that you still need, you have to make a backup of the data before you proceed.

Now we can delete the filesystem of our USB flash drive. To do this we can use wipefs for this again.

sudo wipefs -a /dev/sdb

Next, we need to create the new partition table. However, the partition table needs to be of the GPT type. fdisk that we used before to create the partition table seems to support it. However, I have only been able to create the correct partition table using a tool called parted (read more about it here). Maybe I will find out how to do the same thing using fdisk in the future but for now let's use parted. So, let's create the partition table and specify that it should be of type GPT.

sudo parted /dev/sdb mklabel gpt

After running the above command it could happen that you get the following message.

Information: You may need to update /etc/fstab.

In this thread on reddit.com someone says that this message is displayed by several partition editors when creating a new partition to indicate that you need to add it to /etc/fstab if you want to have it mounted on boot. Since we don't want to have it mounted when booting our machine (it is portable device and not our internal hard drive!), we can ignore this message I think.

Note: GPT and MBR are two different types of partition tables. If you are interested in the details of both of these types, you can read more about them here and here.

Next, let's create our partition that encompasses the whole space of our USB flash drive.

sudo parted -a optimal /dev/sdb mkpart primary '0%' '100%'

The message regarding /etc/fstab could appear again but as mentioned above I think we can ignore it. Finally, we need to add a Microsoft related flag called msftdata (read more about it here) on our newly created partition in the following way.

 sudo parted <DEVICE> set <PARTITION_NUMBER> msftdata on

In my case the command was as follows.

sudo parted /dev/sdb set 1 msftdata on

Again, the message regarding /etc/fstab can appear but as before you can probably ignore it. Now we can finally create the file system.

sudo mkfs.exfat -n bam098 /dev/sdb1

Again, bam098 is the name that I decided to give my USB flash drive. You can use any name you like here. After running the command we should see the following or a similar output.

mkexfatfs 1.2.8
Creating... done.
Flushing... done.
File system created successfully.

Let's also make sure again that there are no errors.

sudo fsck.exfat /dev/sdb1

We should see the following or a similar output.

exfatfsck 1.2.8
Checking file system on /dev/sdb1.
File system version           1.0
Sector size                 512 bytes
Cluster size                 32 KB
Volume size                  14 GB
Used space                    2 MB
Available space              14 GB
Totally 0 directories and 0 files.
File system checking finished. No errors found.

We should make sure that it says No errors found. Additionally, we can also unplug the USB flash drive from our machine and plug it in again. When running df it should now appear in the list of mounted devices.

/dev/sdb1                    15112192      2048  15110144   1% /media/bam/bam098

Finally, I tested my USB flash drive, formatted as exFat, on Ubuntu 18.04 LTS, MacOS Catalina and Windows 10. It worked on all three operating systems this time. So, we are done!