Mike Slinn

Linking Directories on NTFS and Ext4 Volumes

Published 2022-02-07. Last modified 2023-08-06.
Time to read: 2 minutes.

This page is part of the posts collection, categorized under Bash, Ubuntu, WSL, WSL2.

Sometimes I need to insert some code into a program that depends on the type of format that a drive volume has. For example, today I need to either make a Windows junction to connect two directories on NTFS volumes. On the other hand, if one or both directories were on other types of volumes, I would have to connect the directories using a Linux symlink.

All of the bash scripts shown in this article are meant to run in a Bash shell running on WSL or WSL2.

Use Windows Junctions When Possible

When working on WSL, Windows junctions are more desirable than Linux hard links and symlinks because junctions are visible in Windows and also in WSL. Unlike Linux hard links, which only work within a single volume, Windows junctions can span two volumes. Linux symlinks are only visible from WSL; a symlinked directory only appears as a useless file when viewed from Windows.

Both directories need to be on NTFS volumes to make a Windows junction between them. Junctions are permitted within a single NTFS volume, or between two NTFS volumes. Linux symlinks can be used on all volume types, but only work properly when viewed from Linux.

Windows junctions are shown with a small arrow icon in Windows File Manager. In the image above, the curriculum directory is a junction.

Determining a Volume Type

I wrote the volumeType bash function to obtain the type of the volume that contains a file or directory. Linux ext4 volumes have partition type ext4. NTFS volumes have partition type 9p.

Shell
function volumeType {
  # Usually returns volume types ext4 or 9p (for NTFS)
  df -Th "$1" | tail -n 1 | awk '{print $2}'
}

Here are examples of using volumeType:

Shell
$ volumeType /mnt/c  # Under WSL/WSL2 this is usually NTFS
9p 
$ volumeType / # For Ubuntu this defaults to ext4 ext4

All of the remaining scripts on this page either return a value (indicating true), or they do not return anything (indicating false).

Two more bash functions test if a file or directory is part of an NTFS or ext4 volume:

Shell
function isNTFS {
  if [ "$( volumeType "$1" )" == 9p ]; then echo yes; fi
}
function isExt4 { if [ "$( volumeType "$1" )" == ext4 ]; then echo yes; fi }

Here are examples of using isNTFS and isExt4:

Shell
$ isNTFS /mnt/c
yes 
$ isExt4 /mnt/c
$ isNTFS /
$ isExt4 / yes

Windows Junctions

The bothOnNTFS bash function indicates if both of the paths passed to it are on NTFS volumes.

Shell
function bothOnNTFS {
  if [ "$( isNTFS "$1" )" ] && [ "$( isNTFS "$2" )" ]; then echo yes; fi
}

Let's try out bothOnNTFS.

Shell
$ bothOnNTFS /mnt/c /mnt/f
yes 
$ bothOnNTFS /mnt/c /

bothOnNTFS lets us decide how to connect two directories. If they are both on NTFS volumes, we can connect them using a Windows junction; otherwise we'll need to symlink them.

Connecting Via a Windows Junction or Linux Symlink

We could either make a Windows junction using the mklink command, or we could make a Linux symlink using the ln -s command. Notice how the order of parameters between mklink is the reverse of the order of the Linux ln command.

Shell
if [ $( bothOnNTFS "$cadenzaCurriculum" . ) ]; then
    WINDOWS_PATH="$( wslpath -w "$cadenzaCurriculum/site_$TITLE" )"
    echo "Making Windows junction from $cadenzaCurriculum/site_$TITLE to curriculum/"
    cmd.exe /C mklink /j curriculum "$WINDOWS_PATH"
else
  echo "Symlinking $cadenzaCurriculum/site_$TITLE to curriculum/"
  ln -s "$cadenzaCurriculum/site_$TITLE" curriculum
fi
When the above code ran it produced:
Shell
Making Windows junction from /mnt/f/work/cadenzaHome/cadenzaCurriculum/site_ScalaCourses.com to curriculum/
Junction created for curriculum <<===>> F:\work\cadenzaHome\cadenzaCurriculum\site_ScalaCourses.com

Windows Junction for Windows Home in Ubuntu

Neither Linux nor Java appreciate spaces in directories. Spaces in home directories are by nature problematic. If you have a space in your home directory on Windows, you can use the PowerShell New-Item commandlet to create an equivalent junction to a new directory node without spaces in the name.

The following uses the PowerShell New-Item commandlet to create a new directory called C:\Users\mslinn, accessible from WSL as /mnt/c/mslinn, which points to the same directory as C:\Users\Mike Slinn.

PowerShell
PS C:\Users\Mike Slinn> ni "C:\Users\mslinn" -i SymbolicLink -ta "C:\Users\Mike Slinn"
* indicates a required field.

Please select the following to receive Mike Slinn’s newsletter:

You can unsubscribe at any time by clicking the link in the footer of emails.

Mike Slinn uses Mailchimp as his marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp’s privacy practices.