Published 2022-02-07.
Last modified 2023-08-06.
Time to read: 2 minutes.
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
.
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
:
$ 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:
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
:
$ 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.
function bothOnNTFS { if [ "$( isNTFS "$1" )" ] && [ "$( isNTFS "$2" )" ]; then echo yes; fi }
Let's try out bothOnNTFS
.
$ 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.
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
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:\
,
accessible from WSL as /mnt/
,
which points to the same directory as C:\Users\
.
PS C:\Users\Mike Slinn> ni "C:\Users\mslinn" -i SymbolicLink -ta "C:\Users\Mike Slinn"