File Exchange

image thumbnail

GetFullPath

version 1.7 (17.5 KB) by

Full path name for partial or relative path

43 Downloads

Updated

View License

Editor's Note: This file was selected as MATLAB Central Pick of the Week

GetFullPath - Get absolute path of a file or folder name
This function converts a partial or relative name to an absolute full path name. The fast Mex works on Windows only, but the M-file runs on Windows, MacOS and Unix.
FullName = GetFullPath(Name, Style)
INPUT:
Name: String or cell string, file or folder name with relative or absolute path.
UNC paths accepted. Path need not exist.
Style: Special styles for long file names under Windows:
'auto': Add '//?/' for long names (> 255 characters).
'lean': No '//?/'.
'fat': '//?/' added for short names also.
Optional, default: 'auto'.

OUTPUT:
FullName: String or cell string, file or folder name with absolute path.

EXAMPLES:
cd(tempdir); % Assuming C:\Temp here
GetFullPath('File.Ext') % ==> 'C:\Temp\File.Ext'
GetFullPath('..\File.Ext') % ==> 'C:\File.Ext'
GetFullPath('.\File.Ext') % ==> 'C:\Temp\File.Ext'
GetFullPath('*.txt') % ==> 'C:\Temp\*.txt'
GetFullPath('D:\Folder1\..\Folder2') % ==> 'D:\Folder2'
GetFullPath('\') % ==> 'C:\', current drive!
GetFullPath('Folder\') % ==> 'C:\Temp\Folder\'
GetFullPath('\\Server\Folder\Sub\..\File.ext')
% ==> '\\Server\Folder\File.ext'

Alternatives:
WHICH: only for existing files, ~24 times slower.
System.IO.FileInfo: .NET (thanks Urs), more features, ~50 times slower.
java.io.File: "/.." and "/." are fixed by getCanonicalPath (~6 times slower),
but no completing of partial/relative path.

Tested: Matlab 6.5, 2008a, 2009a, 2011b, WinXP/32, Win7/64
Installation: See Readme.txt

Suggestions and question by email or in the comment section are very welcome.

Comments and Ratings (33)

StefanoMas

Jan Simon

Jan Simon (view profile)

@Max: My first reply vanished magically. Again:

Thanks for reporting the problem. It is caused by a bugg of Matlab's FULLFILE which replies 'C:\\' for FULLFILE('C:'\', '\') since R2015b. See <http://www.mathworks.com/matlabcentral/fileexchange/55474-joinpath-arg1--arg2--varargin-> . I'm going to hack the unit-test function and insert a work-around.

To run a unit-test, Matlab must be able to find the file. You can save the M and MEX files in an own folder and attach it to Matlab's PATH temporarily using addpath(). Because the tests for folder access requires changing the current folder, it cannot rely on the current folder. For this reason there is no way for an exhaustive testing without including the parent folder to the path. I do not see, why this is irritating.

When files are uploaded to the FEX, Mathworks inserts the license file automatically. I have no influence to the name, the contents or the location of this file. I see the problem, that if you install several submissions in the same folder, the licence.txt files are overwritten and this is neither useful nor legal. So what about using an own folder for each submission? If you decide not to do this, it is your turn to care for the details.

Jan Simon

Jan Simon (view profile)

@Max: PS. I keep all unit-test functions in a separate folder, from where I start them automatically. For the FEX upload I copied them in the same folder. Checking if the M or Mex version is found by Matlab is a safe test in both setups. As a fallback the unit-test can be started in the current folder also and restores it with an OnCleanup method even in a case of an unexpected crash.

Unit test fails on Windows 8.1 64bit with Matlab R2016b for both the m- and mex-file:

Path: [C:\Users\Username\AppData\Roaming\MathWorks\MATLAB\R2016b\..\..\..\..\..\..\..] ==> error
GetFullPath replied: [C:\]
Expected: [C:\\]
Error using uTest_GetFullPath (line 336)
Error using uTest_GetFullPath (line 330)
uTest_GetFullPath: GetFullPath with folder failed

Moreover, it is quite irritating when even the unit test expects the m- or mex-file to be on the Matlab path. I do not want to install this file in my search path before the unit test completes successfully. Moreover having a license.txt and Readme.txt in the search path, where lots of programs are stored, seems strange to me, too.

Lynn

Lynn (view profile)

Evan

Evan (view profile)

Jie Liang

Very helpful function! This is exactly what I want.

Igor

Igor (view profile)

@Charles: About using "c" instead of "m" - have you tried other submissions, providing similar functionality? Have you tested their performance? As far as I can remember, when I was looking for such a function some time ago, I noticed many "m" implementations were quite slow. Most of them are quite unstable as well. I was happy to find this one - fast and quite reliable. Probably the best of it's kind for Matlab. It's still not perfect, for example, see my comments below. I've voted "5" because it's better that others, not because it's "perfect".
I do strongly agree that it's ridiculous that programmer should think about these things when using such a high-level language.

Jan Simon

Jan Simon (view profile)

@Charles: Microsoft decided not to support path names with more than 260 characters along time ago. The consequences are cruel, e.g. file with such full path names cannot be thrown to the recycle bin in the Windows Explorer and a drag&drop copy to a network drive is not possible also. A lot of other API functions are affected by this restriction. The C-extension allows to use at least one reliable method of the operating system, which can handle even Unicode character sets correctly. But notice, that even the native GetFullPathName API function of Windows does not insert the required \\?\ automatically on demand. Therefore I cannot find any block of code, which can be removed from my function without removing necessary features.

Providing an additional M-file to support Unix and platform independent programs is a fair idea in the FEX. And I have never seen a software, which has been tested too exhaustively.

It is not the question, how much time is spent inside this function, but how much debug time is required to identify and fix errors caused by unusual path names, which are not treated correctly.

Counting code lines -including comment lines and test code- is a strange method to assess the code quality. If you think, you can write some code, which offers the same functionality with less lines, you are invited to do so and publish it here also. You can find more submissions here for this topic, but they consider less exceptions. Therefore I'm still convinced, that this is considered high quality code. Of course, I'd be glad, if such a function is included in Matlab already.

I appreciate any constructive feedback, but "this is more complicated than I expect" is not a helpful criticism, because this depends mainly on your expectations and not on the code.

Charles

I downvoted because of the code quality. There are no less than 831 lines of code across all the m and c files (including tests). 831 lines. For a function that returns the absolute path of a file. Really. Is this really what is considered high quality MATLAB code? A C extension was necessary for this? How much time in your MATLAB code is spent computing the absolute path? Enough to merit writing a C extension? I have a hard time believing that.

Jan Simon

Jan Simon (view profile)

@Charles: I do not see a reason for down-rating, because it is not my fault that there is no built-in function yet.

Charles

It's very concerning that this amount of MATLAB code AND a C extension is needed to get the absolute path of a file AND that this became Pick of the Week. A 30-year-old language still has no native function to get the absolute path of a file.

Igor

Igor (view profile)

If anyone wants to lower the length limit at which GetFullPath generates UNC path, this tiny modification seem to work:

Just under line 86:
-------------------
#include <wchar.h>
-------------------

add the following two lines:
-------------------
#undef MAX_PATH
#define MAX_PATH 230
-------------------

(To test it with ease, one may firstly limit MAX_PATH to, say, 20; and check if GetFullPath would return
--------------------------------------
>> GetFullPath('c:\123456789123456789')
ans =
\\?\c:\123456789123456789
--------------------------------------
).

Jan Simon

Jan Simon (view profile)

@Igor: Thanks for your comments. Even with 257 or 256 some problems remain, e.g. MKDIR requires a path with less than 248 characters (why?):
str = ['C:\Temp\', repmat('abcdefghkl\', 1, 23)]
mkdir(p(1:248)) % Error: filename or extension is too long
The long path cannot be created in the Windows Explorer or deleted to the recycler.
Therefore I still think, that these are limitations of DIR and MKDIR, and it isn't a good idea to include the workarounds in GetFullPath. Enhanced DIR and MKDIR commands would be more efficient and direct.
But to go a step further: Actually this is a problem of Windows, which still suffers from this ridiculous limitations which have been comprehensible in the pre-NTFS times only.

You are welcome to change the limit in the code to 257, and I'm convinced there will still be problems and inconsistencies as for all other limits also. Therefore I'd prefer improved file handling functions instead of adjusting GetFullPath.

Igor

Igor (view profile)

Thanks for the update!
Though, some Matlab functions (like "dir") still fail for 258-long path on my R2012b.

Example:
Just create a directory like this anyhow:

p = 'C:\temp\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\ufolder4'

then:

>> isdir(p)
ans =
1
>> exist(p)
ans =
7
>> length(p)
ans =
258
>> dir(p)
'C:\temp\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\ufolder4' not found.
>> isequal(GetFullPath(p),p)
ans =
1
>> dir(GetFullPath(p)
dir(GetFullPath(p)
|
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.

>> dir(GetFullPath(p))
'C:\temp\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\abcdefghkl\ufolder4' not found.
>> dir(['\\?\' p])

. ..

====================
So, maybe it's worth changing the limit to, say, 257 characters?

Julian

Julian (view profile)

Thanks, very useful; I too have needed this but run into trouble in various ways so never been fully satisfied with my solution. I don't fully understand the C-windows API method, but looks like it is working on my PC... For preparation of paths I can get away with cd(cd('/the/path/string'))...

Jan Simon

Jan Simon (view profile)

Thanks Igor! There is another problem if the the full path has 254 characters. While Windows accept this, Matlab's DIR command doesn't. I'm going to post an improved version soon.

Igor

Igor (view profile)

It looks like I've found another bug - if one try to use an 255+ long UNS path as GetFullPath argument, (for example: nested GetFullPath) this may result in duplicate prefix, i.e. invalid filename.

---------------------------------------
K>> GetFullPath('I:\ROSPAN International\Suzunskoye field\Well 969\X-ray micro-CT\1. Suzun 82180-82181\Tfit\\incomplete\smp_w_fdiff 2012-04-13 20.43.59\\fit_Tall_IR\/fit_Tall_IR_2(inscribed square)//unaligned//Histograms0001/errorbar_runmean_mask (vol1-vol2)_vs_mean(vol1(mask))')
ans =
\\?\I:\ROSPAN International\Suzunskoye field\Well 969\X-ray micro-CT\1. Suzun 82180-82181\Tfit\incomplete\smp_w_fdiff 2012-04-13 20.43.59\fit_Tall_IR\fit_Tall_IR_2(inscribed square)\unaligned\Histograms0001\errorbar_runmean_mask (vol1-vol2)_vs_mean(vol1(mask))
K>> GetFullPath( GetFullPath('I:\ROSPAN International\Suzunskoye field\Well 969\X-ray micro-CT\1. Suzun 82180-82181\Tfit\\incomplete\smp_w_fdiff 2012-04-13 20.43.59\\fit_Tall_IR\/fit_Tall_IR_2(inscribed square)//unaligned//Histograms0001/errorbar_runmean_mask (vol1-vol2)_vs_mean(vol1(mask))'))
ans =
\\?\UNC\?\I:\ROSPAN International\Suzunskoye field\Well 969\X-ray micro-CT\1. Suzun 82180-82181\Tfit\incomplete\smp_w_fdiff 2012-04-13 20.43.59\fit_Tall_IR\fit_Tall_IR_2(inscribed square)\unaligned\Histograms0001\errorbar_runmean_mask (vol1-vol2)_vs_mean(vol1(mask))
K>>

Oscar

Oscar (view profile)

Kiran

Kiran (view profile)

Paul Sexton

I was having the same problem as Daniel (with the 01May2011 version). Using the 03Nov2011 version fixes that behavior.

Running the tests on Linux (32-bit) still breaks though:

>> uTest_GetFullPath
==== Test GetFullPath 09-Dec-2011 14:21:31
Function: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/GetFullPath.m
Current path: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011

ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011, Folder: [Folder/]
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011, File: File
ok: ../Folder/
ok: ../../Folder/
ok: ../../../Folder/
ok: ../../../../Folder/
ok: ../../../../../Folder/
ok: ../File
ok: ../../File
ok: ../../../File
ok: ../../../../File
ok: ../../../../../File
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../Folder/
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../Folder/
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../Folder/
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../../Folder/
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../../../Folder/
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../File
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../File
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../File
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../../File
ok: /home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/../../../../../File
Path: [/home/psexton/Documents/MATLAB/GetFullPath_03Nov2011/..] ==> error
GetFullPath replied: [/home/psexton/Documents/MATLAB]
Expected: [home/psexton/Documents/MATLAB]
Error using uTest_GetFullPath (line 202)
Error using uTest_GetFullPath (line 196)
uTest_GetFullPath: GetFullPath with folder failed

Jan Simon

Jan Simon (view profile)

@Daniel: I've tried to improve the code, but cannot test it under Linux.

Daniel Shub

I am not sure this works on Linux ...
GetFullPath('/home/test/../')
gives /ho/home/

Igor

Igor (view profile)

Oliver Woodford

Yes, the non-mex version (which I didn't originally see) is very good.

Jan Simon

Jan Simon (view profile)

@Oliver: Or use the shipped M-version, which runs on Win/MacOS/Linux, considers the cases "C:", "..", "." and "~/", and does not change the current path.
If you comment out the warning about the unfound MEX, GetFullPath.m is 2.5 times faster than FULLPATH for files without path, and 40 times faster for file with a realtive or full path (WinXP, 2009a).

Oliver Woodford

For those people wanting a function that works across platforms, doesn't require mexing, and who don't care so much about speed, an alternative is:
http://www.mathworks.com/matlabcentral/fileexchange/23603-fullpath

Jan Simon

Jan Simon (view profile)

Thanks Urs! The doc is fixed.

us

us (view profile)

jan

this should be corrected
- System.IO.FileInfo is a .NET component (available only in more recent ML versions)
- java.io.File is the java class

urs

Exactly what I needed.
I included this GetFullPath into my setup files which prepare the Matlab paths. And now these paths do not contain '\..' anymore. Effect: Matlab uses only one path for a file instead of multiple, which had confused the debugger.

Updates

1.7

Unit test fixed: Consider buggy FULLFILE ov Matlab >= 2015b: FULLFILE('C:\', '\') replies 'C:\\' !

1.7

Improved handling of inputs with '//?/' prefix. 2nd input to control prefix in the output. New InstallMex function.

1.6

C-Mex tested under Win7/64. Improved UNC path support in the M-file. Bugfix for M-file under Linux (thanks Daniel).

1.5

Minor bug: '***' in the ErrorID caused bad messages in case of errors.

1.4

Bugfix in M-version: Treat empty matrix as empty string.

1.3

Accept cell strings as inputs.

1.2

M-Version replied bad path for input with leading separator. GetFullPath('\') is the current drive on Windows.

1.1

Doc updated, function not touched.

MATLAB Release
MATLAB 7.13 (R2011b)

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video

Win prizes and improve your MATLAB skills

Play today