diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7a11efa4b0ea2f997f135b14cc084511ca701da6..6e1d981ce2f7ea6176dffd2e29a9dc70b7d0495a 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -13,6 +13,8 @@ Changed
 
 * The :class:`.TaskThread` now allows an error handler function to be
   specified, which is run on the :mod:`.idle` loop.
+* The :func:`.bids.loadMetadata` function no long resolves sym-links when
+  determining whether a file is contained within a BIDS data set.
 
 
 Deprecated
diff --git a/fsl/utils/bids.py b/fsl/utils/bids.py
index cae75cb4f61a806faa7de5a7d83dc04cb44e7f83..eb36a5dc803f06aa2d4a7bd23cde068513c92253 100644
--- a/fsl/utils/bids.py
+++ b/fsl/utils/bids.py
@@ -18,6 +18,7 @@
 All of the other functions in this module should not be considered part of the
 public API.
 
+.. see:: https://bids-specification.readthedocs.io/en/stable/
 
 .. note::  The `pybids <https://bids-standard.github.io/pybids/>`_ library is
            a more suitable choice if you are after a more robust and featured
@@ -36,8 +37,8 @@ import fsl.utils.path    as fslpath
 
 
 class BIDSFile(object):
-    """The ``BIDSFile`` class parses and stores the entities and suffix contained
-    in a BIDS file. See the :func:`parseFilename` function.
+    """The ``BIDSFile`` class parses and stores the entities and suffix
+    contained in a BIDS file. See the :func:`parseFilename` function.
 
     The :meth:`match` method can be used to compare two ``BIDSFile`` instances.
 
@@ -91,15 +92,9 @@ class BIDSFile(object):
 
 
 def parseFilename(filename):
-    """Parses a BIDS-like file name. The file name must consist of zero or more
-    "entities" (alpha-numeric ``name-value`` pairs), a "suffix", all separated
-    by underscores, and a regular file extension. For example, the following
-    file::
-
-        sub-01_ses-01_task-stim_bold.nii.gz
-
-    has suffix ``bold``, entities ``sub=01``, ``ses=01`` and ``task=stim``, and
-    extension ``.nii.gz``.
+    """Parses a BIDS-like file name, returning the entities and suffix encoded
+    in the name. See the :func:`isBIDSFile` function for an explanation of
+    what is considered to be a valid BIDS file name.
 
     .. note:: This function assumes that no period (``.``) characters occur in
               the body of a BIDS filename.
@@ -161,11 +156,24 @@ def inBIDSDir(filename):
 def isBIDSFile(filename, strict=True):
     """Returns ``True`` if ``filename`` looks like a BIDS image or JSON file.
 
+    A BIDS file name must consist of zero or more "entities" (alpha-numeric
+    ``name-value`` pairs), a "suffix", all separated by underscores, and a
+    regular file extension. For example, the following file::
+
+        sub-01_ses-01_task-stim_bold.nii.gz
+
+    has suffix ``bold``, entities ``sub=01``, ``ses=01`` and ``task=stim``, and
+    extension ``.nii.gz``.
+
     :arg filename: Name of file to check
     :arg strict:   If ``True`` (the default), the file must be within a BIDS
                    dataset directory, as defined by :func:`inBIDSDir`.
     """
 
+    # Zero or more entities because sidecar files
+    # do not necessarily need to contain any
+    # entities (e.g. ``T1w.json`` is valid)
+
     name    = op.basename(filename)
     pattern = r'([a-z0-9]+-[a-z0-9]+_)*([a-z0-9])+\.(.+)'
     flags   = re.ASCII | re.IGNORECASE
@@ -189,7 +197,7 @@ def loadMetadata(filename):
                    ``filename``
     """
 
-    filename  = op.realpath(op.abspath(filename))
+    filename  = op.abspath(filename)
     bfile     = BIDSFile(filename)
     dirname   = op.dirname(filename)
     prevdir   = filename
diff --git a/tests/test_bids.py b/tests/test_bids.py
index a5facaf8ea2727a23e89471bc13e57dee25745f4..4a2bc1e10c76bf03027962eb8cb2f7c4a4551bd8 100644
--- a/tests/test_bids.py
+++ b/tests/test_bids.py
@@ -18,8 +18,11 @@ import fsl.utils.bids  as     fslbids
 
 
 def test_parseFilename():
-    with pytest.raises(ValueError):
-        fslbids.parseFilename('bad_file.txt')
+    badtests = ['bad_file.txt']
+
+    for test in badtests:
+        with pytest.raises(ValueError):
+            fslbids.parseFilename(test)
 
     tests = [
         ('sub-01_ses-01_t1w.nii.gz',
@@ -105,3 +108,41 @@ def test_loadMetadata():
         assert fslbids.loadMetadata(t1) == {**meta2, **meta1}
         json4.write_text(json.dumps(meta4))
         assert fslbids.loadMetadata(t1) == {**meta4, **meta2, **meta1}
+
+
+
+def test_loadMetadata_symlinked():
+    ddreal = Path('a')
+    t1real = Path('b')
+    j1real = Path('c')
+    j2real = Path('d')
+    j3real = Path('e')
+    j4real = Path('f')
+    dd     = Path('data/dataset_description.json')
+    t1     = Path('data/sub-01/func/sub-01_task-stim_bold.nii.gz')
+    json1  = Path('data/sub-01/func/sub-01_task-stim_bold.json')
+    json2  = Path('data/sub-01/sub-01_bold.json')
+    json3  = Path('data/sub-01_t1w.json')
+    json4  = Path('data/sub-01/task-stim_bold.json')
+    meta1  = {'a' : '1',   'b' : '2'}
+    meta2  = {'a' : '10',  'c' : '3'}
+    meta3  = {'a' : '109', 'b' : '99'}
+    meta4  = {'c' : '9',   'd' : '5'}
+
+    with tempdir():
+        ddreal.touch()
+        t1real.touch()
+        j1real.write_text(json.dumps(meta1))
+        j2real.write_text(json.dumps(meta2))
+        j3real.write_text(json.dumps(meta3))
+        j4real.write_text(json.dumps(meta4))
+
+        Path(op.dirname(t1)).mkdir(parents=True)
+        dd   .symlink_to(op.join('..',             ddreal))
+        t1   .symlink_to(op.join('..', '..', '..', t1real))
+        json1.symlink_to(op.join('..', '..', '..', j1real))
+        json2.symlink_to(op.join('..', '..',       j2real))
+        json3.symlink_to(op.join('..',             j3real))
+        json4.symlink_to(op.join('..', '..',       j4real))
+
+        assert fslbids.loadMetadata(t1) == {**meta4, **meta2, **meta1}