File Exchange

image thumbnail

GetFullPath

version 1.8.0.0 (18 KB) by Jan
Full path name for partial or relative path

32 Downloads

Updated 28 May 2019

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 2009a, 2011b, 2018b, WinXP/32, Win7/64, Win10/64
Installation: See ReadMe.txt

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

Cite As

Jan (2019). GetFullPath (https://www.mathworks.com/matlabcentral/fileexchange/28249-getfullpath), MATLAB Central File Exchange. Retrieved .

Comments and Ratings (43)

Jan

Thanks, HHang Li. This is fixed now.

HHang Li

This is a great function.
A small question. Should line 156 of .m version be
File = ['\', File(8:length(File))]; instead of
File = ['\', File(7:length(File))]; ?

Worked like a charm! Great job!

Jan

@Edvard: I cannot reproduce the problem. Please send me the complete autput of the selftest by mail. You find the address in the source code. Thanks.

When running uTest_GetFullPath (m-file version) I receive the following error:
Error using uTest_GetFullPath (line 387)
uTest_GetFullPath: Unexpected prefix for fat
style?! [\\?\C:\C\Server\Share]

Jan

@Wis: This is a limitation of Windows. The names NUL, CON, PRN, AUX, COM1-9, LPT1-9 as well as trailing dots and spaces are not allowed. This is not a feature of GetFullPath and the conversion from "C:\NUL" to "\\.\NUL" is done by the library function of Windows and both cannot be used as file name.

Wis

In Windoze 7 Pro 64, the "NUL" file (like *nix "/dev/null) translates to "\\.\NUL", which is an invalid Windows file name. MATLAB returns "could not open file for write: \\.\NUL"

with R2018b:

>> GetFullPath('C:/cat')

ans =

'C:\cat'

>> GetFullPath('C:/NUL')

ans =

'\\.\NUL'

Jan

@Wis: This is a correct observation. It is not trivial to access the contents of the modern String type inside a C-mex function, which is compatible with Matlab 6.5 to 2018b. The help section was written a long time ago, when the "string" type was not existing. In these times it was usual to call vectors of type CHAR a "string".
I will fix the help text to clarify, that only char vectors and "cell strings" (which means: cells containing char vectors) are accepted as input.
I try to create a workaround for the modern String type, which converts the inputs transparently to CHAR vectors and the result back to a string again.

Wis

"GetFullPath.mexw64" from http://www.n-simon.de/mex

It does not appear to support the "string" datatype, returning the message:

Error using GetFullPath
*** GetFullPath: [FileName] must be a string or cell string.

tested with R2018b

StefanoMas

Jan

@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

@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

Evan

Jie Liang

Very helpful function! This is exactly what I want.

Igor

@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

@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

@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

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

@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

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

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

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

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

Kiran

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

@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

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

Jan

@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).

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

Thanks Urs! The doc is fixed.

us

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.8.0.0

Bugfix in M-File for UNC path.

1.7.0.0

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

1.7.0.0

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

1.6.0.0

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

1.5.0.0

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

1.4.0.0

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

1.3.0.0

Accept cell strings as inputs.

1.2.0.0

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

1.1.0.0

Doc updated, function not touched.

MATLAB Release Compatibility
Created with R2018b
Compatible with any release
Platform Compatibility
Windows macOS Linux