-
Notifications
You must be signed in to change notification settings - Fork 6
/
fuf.m
242 lines (224 loc) · 10.9 KB
/
fuf.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
function srtlist = fuf (folders,reclev,opt)
%FUF recursively retrieves files under specified folder(s).
%
% Syntax: srtlist = fuf (folders,reclev,opt)
%
% INPUT ARGUMENTS
% - folders can be a character array or a cell array of strings. Valid strings
% are matlab path;
% - reclev {1} optional scalar/numeric array of booleans: 1 stands for recursive
% search, whilst 0 limit the search to the specified folder.
% reclev can be either a scalar, or a 1 X length(folders) array.
% Use the 2nd option to specify the search rule on a folder-basis.
% Default is 1, i.d., each folder is searched for recursively.
% - opt {'normal'} | 'detail' is an optional field: when it's set to 'detail',
% FUF returns the full path of files searched for, while, when set to
% normal, it returns file names only.
%
%
% OUTPUT ARGUMENT
% - srtlist is a sorted cell array of strings containing the name or the full path
% of files recursively found under the given folders.
%
% FUF applies the wildcard * for searching files through all the directories beneath the given folder(s)
% if the reclev parameter is set to 1. If you want to have different wildcards for folders belonging
% to the same tree root, you need to pass them separately as input arguments.
%
% REMARKS
% - Folders don't have to belong to the same directory, therefore this function doesn't
% have to be invoked from a particular directory.
% - Matlab partial paths are not valid input arguments.
% - Wildcard * can be used to narrow the search.
% - To get the full path of a given file, FUF doesn't use the which command,
% therefore it normally works also with java function that are not loaded.
% - After completion, the working directory is set to the current directory at the time
% of the function call.
%
% EXAMPLES
%
% To retrieve all files under the folder Utils:
%
% >> dir('C:\matlabR12\work\Interface\Utils')
%
% . Contents.m
% .. my_interface_evalmcw.m
%
% To retrieve recursively the full path of all .m files starting with Cont under the folder work:
%
% >> fuf('C:\matlabR12\work\Con*.m','detail')
%
% 'C:\matlabR12\work\Laboratorio_modellistica\DTT\Contents.m'
% 'C:\matlabR12\work\Laboratorio_modellistica\SDF\Contents.m'
% 'C:\matlabR12\work\PREPOSTGUIS\Contents.m'
% 'C:\matlabR12\work\PREPOSTGUIS\Utils\Contents.m'
% 'C:\matlabR12\work\Pavia\Contents.m'
% 'C:\matlabR12\work\TwoLe_front_end\Contents.m'
% [1x74 char]
% 'C:\matlabR12\work\TwoLe_front_end\My_Classes\@Sector\Contents.m'
% 'C:\matlabR12\work\TwoLe_front_end\Utils\Contents.m'
% 'C:\matlabR12\work\Utils\Contents.m'
%
% To retrieve recursively under the folder PREPOSTGUIS all .fig files and non recursively, under
% the folder MatlabR12 all .txt files:
%
% >> fuf({'C:\matlabR12\work\PREPOSTGUIS\*.fig','C:\matlabR12\*.txt'},[1,0],'detail')
%
% 'C:\matlabR12\license.txt'
% 'C:\matlabR12\work\PREPOSTGUIS\Private\MV_Manager.fig'
% 'C:\matlabR12\work\PREPOSTGUIS\R_h.fig'
% 'C:\matlabR12\work\PREPOSTGUIS\TSA.fig'
% 'C:\matlabR12\work\PREPOSTGUIS\Visual_3D.fig'
% -$-$-$-
%
% Author: Francesco di Pierro Reasearch Assistant
% Center for Water Systems (CWS)
% Dep. of Engineering and Computer Science
% University of Exeter
% e-mail: <F.Di-Pierro@ex.ac.uk>
%
% -$-$-$-
%--------------------CHECK INPUT ARGUMENT TYPE AND SET DEFAULT VALUES------------------------%
%argument cheking and parsing default parameters
error(nargchk(1,3,nargin));
error(nargoutchk(0,1,nargout));
INITIAL_DIR = pwd;
if nargin==1
if ischar(folders)
folders = cellstr(folders);
elseif ~iscellstr(folders)
error('The 1st argument to the function fuf must be either a string or a cellstring!')
end
reclev = ones(size(folders));
opt = 'normal';
elseif nargin==2
if ischar(folders)
folders = cellstr(folders);
elseif ~iscellstr(folders)
error('The 1st argument to the function fuf must be either a string or a cellstring!')
end
if isnumeric(reclev)
if ~all(ismember(reclev,[0,1]))
error('The 2nd argument to the function must be a scalar/vector of booleans!')
end
if prod(size(reclev))==1
reclev = reclev*ones(size(folders));
elseif prod(size(reclev))~=prod(size(folders))
error('The 2nd argument to the function must be a either a scalar or a 1 X length(1st argument) array!')
end
opt = 'normal';
elseif ~ischar(reclev) | ~any(strcmp(reclev,{'normal','detail'}))
error('Mismatched argument specification; the 3rd argument can be either set to ''normal'' or ''detail''');
else
opt = reclev;
reclev = ones(size(folders));
end
else
if ischar(folders)
folders = cellstr(folders);
elseif ~iscellstr(folders)
error('The 1st argument to the function fuf must be either a string or a cellstring!')
end
if isnumeric(reclev)
if ~all(ismember(reclev,[0,1]))
error('The 2nd argument to the function must be a scalar/vector of booleans!')
end
if prod(size(reclev))==1
reclev = reclev*ones(size(folders));
elseif prod(size(reclev))~=prod(size(folders))
error('The 2nd argument to the function must be a either a scalar or a 1 X length(1st argument) array!')
end
else
error('The 2nd argument to the function must be a scalar/vector of booleans!')
end
if ~ischar(opt) | ~any(strcmp(opt,{'normal','detail'}))
error('Mismatched argument specification: Tte 3rd argument to the function must be either set to ''normal'' or ''detail''');
end
end
%scan folders searching for incorrect folder names and partialpaths!!!
EXIT = 0;
for i=1:length(folders)
[d,f,e] = fileparts(folders{i});
if (~isdir(d) & ~isempty(e))
warning(['"',d,'" is not a valid folder name!'])
EXIT = 1;
elseif (~isdir(fullfile(d,f,'')) & isempty(e))
warning(['"',fullfile(d,f,''),'" is not a valid folder name!'])
EXIT = 1;
elseif (isempty(dir(d)) & ~isempty(e)) | (isempty(dir(fullfile(d,f,''))) & isempty(e))
warning('Matlab PARTIALPATHS not allowed!')
EXIT = 1;
else %this cheks the very unlike event arising
sub = dir(pwd); %when the partial path provided is a directory
[subel{1:length(sub)}] = deal(sub.name); %under the current one: this, in fact, is the
[subtype{1:length(sub)}] = deal(sub.isdir); %only situation where the dir command handles
testel1 = strcmp(subel,fullfile(d,f,'')); %partialpaths!!!
testel2 = strcmp(subel,d);
if ~isempty(subtype(testel1)) | ~isempty(subtype(testel2))
warning('Matlab PARTIALPATHS not allowed!')
EXIT = 1;
end
end
end
if EXIT
disp('')
error(strvcat('One or more not valid folder names encountered! Function aborted!'))
end
%--------------------------------CORE FUNCTION--------------------------------%
sorted_list = []; %initialize the output list
sorted_list = rec(sorted_list,folders,reclev,opt); %call the function
sorted_list = sortrows(sorted_list); %sort the list
if nargout, srtlist = sorted_list; else disp (' '),disp(sorted_list), end
cd(INITIAL_DIR); %and set current directory back to the initial one
%--------------------------------RECURSIVE FUNCTION--------------------------------%
function sorted_list = rec(sorted_list,folders,reclev,opt)
for i=1:length(folders)
%first build the new search condition made of all files satistying the
%search condition and all directories under the current one
val = []; val1 = []; val2 = []; cnval1 = {}; cnval2 = {}; cdval = {}; cdva2 = {}; %initialize helper variables
[pth,fname,ext] = fileparts(folders{i});
cd(pth); %move to the directory: isdir only recognizes directories on the Matlab search path or the current one!
if isdir(fname)
wild = '';
cd(fname)
pth = fullfile(pth,fname);
val = dir;
else
%get the filenames satisfying the search condition
val1 = dir(folders{i});
wild = [fname,ext];
if isempty(val1)
cnval1 = []; cdval1 = [];
else
[cnval1{1:length(val1)}] = deal(val1.name); [cdval1{1:length(val1)}] = deal(val1.isdir);
end
%and the directory/ies under the current one
val2 = dir;
wo = logical(zeros(size(val2)));
for k=1:length(val2)
if val2(k).isdir
wo(k) = 1;
end
end
val2(~wo) = [];
%and build the new search structure
[cnval2{1:length(val2)}] = deal(val2.name); [cdval2{1:length(val2)}] = deal(val2.isdir);
cnval = [cnval1,cnval2]; cdval = [cdval1,cdval2];
[val(1:length(cnval)).name] = deal(cnval{:}); [val(1:length(cdval)).isdir] = deal(cdval{:});
end
for j=1:length(val)
if (val(j).isdir) & not(strcmp(val(j).name,'.')) & not(strcmp(val(j).name,'..')) %if the jth object under the ith folder is a valid folder name(directory)...
new_path = fullfile(pth,val(j).name); %set the current directory to that one:
cd(new_path);
if reclev(i) %recursively call the function keeping in mind the search condition
sorted_list = rec(sorted_list,{fullfile(new_path,wild)},reclev(i),opt);
end
cd .. %get back to the previous directory
elseif not(strcmp(val(j).name,'.')) & not(strcmp(val(j).name,'..')) %if the jth object under the ith folder is a valid file name
if strcmp(opt,'detail')
sorted_list =[sorted_list; cellstr(fullfile(pwd,val(j).name))];
else
sorted_list =[sorted_list; cellstr(val(j).name)];
end
end
end
end