Different paths that point to the same file on macOS

I need to save the relative path for a sample file. For this, I combine the sample path with the path the user chooses to save the preset.

// The path where the user loaded the sample:
/Users/user/Google Drive/My Drive/SoundNetwork/Samples/Drums/808 Kit/808 kick01.wav

// The path returned by the native File Save dialog:
/Users/user/My Drive/SoundNetwork/Samples/Drums/808 Kit

Both paths above point to the same directory. But the paths strings are not the same. And JUCE can’t combine them into a relative path.

File(samplePath).getRelativePathFrom(presetPath.getParentDirectory())

Returns:

…/…/…/…/Google Drive/My Drive/SoundNetwork/Samples/Drums/808 Kit/808 kick01.wav

I would expect the following result:

808 kick01.wav

I wonder if there is something I can do about this. It looks to me like one of the paths includes a symlink. Is there a way to get the real path in every case?

I don’t know if JUCE has any support for this, but I do know that on macOS you can use -[NSString stringbystandardizingpath:] to resolve symlinks and expand the tilde character if present. There’s also the POSIX realpath() which should be simpler to use from C++.

1 Like

Seems that JUCE isn’t handling this within getRelativePathFrom and is just working with its internal string representation of the paths, but you might be able to resolve the symlinks first using:

File::isSymbolicLink and File::getLinkedTarget

although you could probably just skip testing if its a symbolic link as the docs for getLinkedTarget say:

If this file is a link or alias, this returns the file that it points to.

If the file isn’t actually (a) link, it’ll just return itself.

JUCE team n.b. : Small typo in the docs, missing the “a”. Not massively important though!

1 Like

Thanks for the answer. I tried File::getLinkedTarget but it looks like this works only if the folder on the top is a symbol link, but not when it is a subdirectory.
I will see if I can parse the path and replace the symbol links with the real path in my code.

A JUCE intern function that cleans up a file path and resolves things like this would be very handy. At the moment it is hard to find out if two paths point to the same target.

This probably also would help to find out if two files are the same with juce::File::moveFileTo(). At the moment the file may be deleted when the destination folder is the same as the source folder but with different path strings.

I was a bit too lazy to implement this myself. I ended up with the following code for the moment:

static juce::File getRealPath(juce::File file)
{
    #if !JUCE_WINDOWS
    char buf[PATH_MAX];
    realpath(file.getFullPathName().toRawUTF8(), buf);
    juce::File fileNew = juce::File(juce::String(buf));
    file = fileNew;
    #endif

    return file;
}