comparison scripts/miscellaneous/fullfile.m @ 19598:c304687571c8

fullfile.m: properly process file separators and drive letters on Windows systems (bug #43926)
author Philip Nienhuis <prnienhuis@users.sf.net>
date Sun, 11 Jan 2015 20:11:43 +0100
parents 8cc4a9bb253b
children db92e7e28e1f
comparison
equal deleted inserted replaced
19595:0d3e67f27d57 19598:c304687571c8
21 ## @deftypefnx {Function File} {@var{filenames} =} fullfile (@dots{}, @var{files}) 21 ## @deftypefnx {Function File} {@var{filenames} =} fullfile (@dots{}, @var{files})
22 ## Build complete filename from separate parts. 22 ## Build complete filename from separate parts.
23 ## 23 ##
24 ## Joins any number of path components intelligently. The return value 24 ## Joins any number of path components intelligently. The return value
25 ## is the concatenation of each component with exactly one file separator 25 ## is the concatenation of each component with exactly one file separator
26 ## between each non empty part. 26 ## between each non empty part and at most one leading and/or trailing file
27 ## separator.
27 ## 28 ##
28 ## If the last component part is a cell array, returns a cell array of 29 ## If the last component part is a cell array, returns a cell array of
29 ## filepaths, one for each element in the last component, e.g.: 30 ## filepaths, one for each element in the last component, e.g.:
30 ## 31 ##
31 ## @example 32 ## @example
35 ## /home/username/data/f2.csv 36 ## /home/username/data/f2.csv
36 ## /home/username/data/f3.csv 37 ## /home/username/data/f3.csv
37 ## @end group 38 ## @end group
38 ## @end example 39 ## @end example
39 ## 40 ##
41 ## On Windows systems, while forward slash file separators do work, they
42 ## are replaced by backslashes; in addition drive letters are stripped of
43 ## leading file separators to obtain a valid file path.
44 ##
40 ## @seealso{fileparts, filesep} 45 ## @seealso{fileparts, filesep}
41 ## @end deftypefn 46 ## @end deftypefn
42 47
43 ## Author: Carnë Draug <carandraug@octave.org> 48 ## Author: Carnë Draug <carandraug@octave.org>
44 49
47 if (nargin && iscell (varargin{end})) 52 if (nargin && iscell (varargin{end}))
48 filename = cellfun (@(x) fullfile (varargin{1:end-1}, x), varargin{end}, 53 filename = cellfun (@(x) fullfile (varargin{1:end-1}, x), varargin{end},
49 "UniformOutput", false); 54 "UniformOutput", false);
50 else 55 else
51 non_empty = cellfun ("isempty", varargin); 56 non_empty = cellfun ("isempty", varargin);
57 if (ispc && ! isempty (varargin))
58 varargin = strrep (varargin, "/", filesep);
59 varargin(1) = regexprep (varargin{1}, '[\\/]*([a-zA-Z]:[\\/]*)', "$1");
60 endif
52 filename = strjoin (varargin(! non_empty), filesep); 61 filename = strjoin (varargin(! non_empty), filesep);
53 filename(strfind (filename, [filesep filesep])) = ""; 62 filename(strfind (filename, [filesep filesep])) = "";
54 endif 63 endif
55 64
56 endfunction 65 endfunction
57 66
58 67
59 %!shared fs, fsx, xfs, fsxfs, xfsy 68 %!shared fs, fsx, xfs, fsxfs, xfsy, xfsyfs
60 %! fs = filesep (); 69 %! fs = filesep ();
61 %! fsx = [fs "x"]; 70 %! fsx = [fs "x"];
62 %! xfs = ["x" fs]; 71 %! xfs = ["x" fs];
63 %! fsxfs = [fs "x" fs]; 72 %! fsxfs = [fs "x" fs];
64 %! xfsy = ["x" fs "y"]; 73 %! xfsy = ["x" fs "y"];
74 %! xfsyfs = ["x" fs "y" fs];
75
65 %!assert (fullfile (""), "") 76 %!assert (fullfile (""), "")
66 %!assert (fullfile (fs), fs) 77 %!assert (fullfile (fs), fs)
67 %!assert (fullfile ("", fs), fs) 78 %!assert (fullfile ("", fs), fs)
68 %!assert (fullfile (fs, ""), fs) 79 %!assert (fullfile (fs, ""), fs)
69 %!assert (fullfile ("", fs), fs) 80 %!assert (fullfile ("", fs), fs)
80 %!assert (fullfile (fs, "x"), fsx) 91 %!assert (fullfile (fs, "x"), fsx)
81 %!assert (fullfile (fs, xfs), fsxfs) 92 %!assert (fullfile (fs, xfs), fsxfs)
82 %!assert (fullfile (fsx, fs), fsxfs) 93 %!assert (fullfile (fsx, fs), fsxfs)
83 %!assert (fullfile (fs, "x", fs), fsxfs) 94 %!assert (fullfile (fs, "x", fs), fsxfs)
84 95
85 %!assert (fullfile ("a/", "/", "/", "b", "/", "/"), "a/b/") 96 %!assert (fullfile ("x/", "/", "/", "y", "/", "/"), xfsyfs)
86 %!assert (fullfile ("/", "a/", "/", "/", "b", "/", "/"), "/a/b/") 97 %!assert (fullfile ("/", "x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
87 %!assert (fullfile ("/a/", "/", "/", "b", "/", "/"), "/a/b/") 98 %!assert (fullfile ("/x/", "/", "/", "y", "/", "/"), [fs xfsyfs])
88 99
89 ## different on purpose so that "fullfile (c{:})" works for empty c 100 ## different on purpose so that "fullfile (c{:})" works for empty c
90 %!assert (fullfile (), "") 101 %!assert (fullfile (), "")
91 102
92 %!assert (fullfile ("a", "b", {"c", "d"}), {"a/b/c", "a/b/d"}) 103 %!assert (fullfile ("x", "y", {"c", "d"}), {[xfsyfs "c"], [xfsyfs "d"]})
93 104
105 %% Windows specific - drive letters and file sep type
106 %!test
107 %! if (ispc)
108 %! assert (fullfile ('\/\/\//A:/\/\', "x/", "/", "/", "y", "/", "/"), ...
109 %! ['A:\' xfsyfs]);
110 %! endif
111
112 %% Windows specific - drive letters and file sep type, cell array
113 %!test
114 %! if (ispc)
115 %! tmp = fullfile ({"\\\/B:\//", "A://c", "\\\C:/g/h/i/j\/"});
116 %! assert (tmp{1}, 'B:\');
117 %! assert (tmp{2}, 'A:\c');
118 %! assert (tmp{3}, 'C:\g\h\i\j\');
119 %! endif