📄 findfiles.m
字号:
function [filesfound, numberfound] = findfiles(varargin)
% findfiles - Linux/UNIX-like find command/function
%
% returns a list in which all files are listed that match one of the
% patterns.
%
% FORMAT:
% [files, number] = findfiles(startfolder, patterns, opts, ....)
%
% - startfolder <char array> folder where to start search
% - patterns <cell array <char array>> file patterns (shell-like)
% (alt.) <char array> : single pattern
% - opt <struct array>: optional parameters in the form of
% .cellstr <double array>: if set and !0 -> return as cellstr
% .chararr <double array>: if set and !0 -> return as char array
% .depth <double array>: sets both minimum and maximum depth
% .dirs <double array>: if set and !0 -> dirs instead of files
% .filesize <double array>: if set and !0 -> only matching files
% .maxdepth <double array>: maximum depth where to search
% .mindepth <double array>: minimum depth where to search
% .maxage <double array>: seconds file must have changed in
% .minage <double array>: seconds file must not have changed in
% .oneperdir <double array>: if set and !0 -> only first match
% .relative <... array> : if set -> !0 -> './' // char array
%
% when used as a command, multiple opts can be given as multiple arguments,
% seperated by spaces (' '):
%
% findfiles /search/folder *mypattern*.txt depth=3 oneperdir=1 relative=./
%
% when used in functional context, a second return value, the number
% of matching files, can be obtained:
%
% [files,number] = findfiles('/where','*.txt');
%
% NOTE: the minage/maxage feature only fully works when the system
% returns English-style month in calls to dir. i.e. under Linux, set the
% LANG environmental setting to 'en_US' before starting up MatLab
% Version: v0.7a
% Build: 7080813
% Date: Aug-08 2007, 1:52 PM CEST
% Author: Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools
%
% TODO: make the returning object (cell) a persistent value to increase
% speed by not having to return it from recursive calls !!!
%
% enough arguments ?
if nargin < 1
error( ...
'BVQXtools:TooFewArguments',...
'Too few arguments. Try ''help %s''.',...
mfilename ...
);
end
if nargin == 1
varargin{2} = varargin{1};
varargin{1} = pwd;
end
% shortcut variable
fsep = filesep;
% sanity checks: startfolder
startfolder = varargin{1};
if ischar(startfolder) && ...
~isempty(startfolder)
% does startfolder contain an asterisk?
if any(startfolder == '?' | startfolder == '*')
% then put startfolder into a cell array to treat this case
[filesfound, numberfound] = findfiles({startfolder}, varargin{2:end});
return;
end
% startfolder is a list of folders
elseif iscell(startfolder) && ...
~isempty(startfolder)
% generate expanded list
nstartfolder = cell(0);
% iterate over items
for nelem = 1:numel(startfolder)
% must be non-empty char
if ~ischar(startfolder{nelem}) || ...
isempty(startfolder{nelem})
error( ...
'BVQXtools:BadArgument',...
'Bad startfolder argument.' ...
);
end
% expand pattern?
if ~any(startfolder{nelem} == '?' | startfolder{nelem} == '*')
% put into final list
nstartfolder{end+1} = startfolder{nelem};
% or look up matching folders
else
% split along possible path separators
[pparts, cparts] = splittocell(startfolder{nelem}, '/\', 1, 1);
if any('/\:' == startfolder{nelem}(1))
pparts = [{''}, pparts];
cparts = cparts + 1;
end
% look for first pattern
for cpart = 1:cparts
if any(pparts{cpart} == '?' | pparts{cpart} == '*')
break;
end
end
% if the pattern occurs in first part, look in current dir
if cpart==1
[pfolders, npfolders] = findfiles('.', ...
pparts{1}, ...
struct('dirs', 1, 'depth', 1));
% otherwise glue first parts together and look up matches
else
[pfolders, npfolders] = findfiles( ...
gluetostring({pparts{1:(cpart-1)}},fsep), ...
pparts{cpart}, ...
struct('dirs', 1, 'depth', 1));
end
% the pattern was not in last part
if cpart < cparts
% put remaining parts back on
for ppart = 1:npfolders
pfolders{ppart} = [pfolders{ppart} fsep ...
gluetostring({pparts{(cpart+1):end}},fsep)];
end
end
% put results at end of list
nstartfolder = [nstartfolder, pfolders];
end
end
% we start with no files found
filesfound = cell(0);
% for each folder in list
for nelem = 1:length(nstartfolder)
% if there (iteratively) remains a pattern char, redo this
if any(nstartfolder{nelem} == '?' | nstartfolder{nelem} == '*')
filesfound = [filesfound(1:end); ...
findfiles({nstartfolder{nelem}}, varargin{2:end})];
% otherwise get files in this folder and put at end of array
elseif exist(nstartfolder{nelem}, 'dir') == 7
filesfound = [filesfound(1:end); ...
findfiles(nstartfolder{nelem}, varargin{2:end})];
end
end
% report the total number found
numberfound = length(filesfound);
return;
% illegal first argument
else
error( ...
'BVQXtools:BadArgument',...
'Bad startfolder argument.'...
);
end
% we're now going for the single folder case and startfolder is OK
% append missing fsep if needed
if startfolder(end) ~= fsep
startfolder = [startfolder fsep];
end
% startfolder exists?
if exist(startfolder,'dir') ~= 7
error( ...
'BVQXtools:FolderNotFound',...
'Startfolder (%s) not found or no folder.',...
strrep(startfolder,'\','\\') ...
);
end
% - sanity checks patterns
patterns = varargin{2};
% default is cell, otherwise
if ~iscell(patterns)
% if is character, put into cell
if ischar(patterns)
patterns = { patterns };
% otherwise bail out
else
error( ...
'BVQXtools:BadArgument', ...
'Patterns must either be a single string or a cell array!' ...
);
end
end
% check each pattern
for count = 1:size(patterns,2)
% only accept chars
if ~ischar(patterns{count}) || ...
~any(patterns{count} == '?' | patterns{count} == '*')
error( ...
'BVQXtools:BadArgument', ...
'All patterns cell contents must be char patterns!' ...
);
end
end
% option argument parsing, default options
if nargin < 3
opt.dirs = 0;
opt.filesize = 0;
opt.maxdepth = 0;
opt.mindepth = 0;
opt.maxage = -1;
opt.minage = -1;
opt.oneperdir = 0;
opt.relative = 0;
opt.return = 'cellarr';
opt.rfolder = startfolder;
% parse options
else
opt = varargin{3};
% non-struct options
if ~isstruct(opt)
% yet start with default struct
clear opt;
opt.dirs = 0;
opt.filesize = 0;
opt.maxdepth = 0;
opt.mindepth = 0;
opt.maxage = -1;
opt.minage = -1;
opt.oneperdir = 0;
opt.relative = 0;
opt.return = 'cellarr';
opt.rfolder = startfolder;
% parse all arguments
for acount=3:nargin
% char option
if ischar(varargin{acount})
% get argument name
argnv = splittocell(varargin{acount}, '=', 1);
oname = argnv{1};
% and possible option value
if size(argnv,2) > 1
oval = argnv{2};
else
oval = '';
end
% only accept known arguments
switch lower(oname)
% option: cellstr, set return type
case {'cellstr'}
oval = str2double(oval);
if oval ~= 0
opt.return = 'cellstr';
end
% option: chararr, set return type
case {'chararr'}
oval = str2double(oval);
if oval ~= 0
opt.return = 'chararr';
end
% option: depth (min and max)
case {'depth'}
if str2double(oval) >= 0
opt.maxdepth = str2double(oval);
opt.mindepth = str2double(oval);
else
opt.maxdepth=0;
opt.mindepth=0;
end
% option: dirs, set lookup type
case {'dirs'}
oval = str2double(oval);
if oval == 0
opt.dirs = 0;
else
opt.dirs = 1;
end
% option: filesize
case {'filesize'}
if str2double(oval) >= 0
opt.filesize = fix(str2double(oval));
else
opt.filesize = 0;
end
% option: maxdepth
case {'maxdepth'}
if str2double(oval) >= 0
opt.maxdepth = fix(str2double(oval));
else
opt.maxdepth = 0;
end
% option: mindepth
case {'mindepth'}
if str2double(oval) >= 0
opt.mindepth = fix(str2double(oval));
else
opt.mindepth = 0;
end
% option: maxage
case {'maxage'}
if str2double(oval) >= 0
opt.maxage = fix(str2double(oval));
else
opt.maxage = -1;
end
% option: minage
case {'minage'}
if str2double(oval) >= 0
opt.minage = fix(str2double(oval));
else
opt.minage = -1;
end
% option: oneperdir
case {'oneperdir'}
oval = str2double(oval);
if oval == 0
opt.oneperdir = 0;
else
opt.oneperdir = 1;
end
% option: relative
case 'relative'
noval = str2double(oval);
if ~isnan(noval)
opt.relative = noval;
if noval < 1
opt.rfolder = startfolder;
else
opt.rfolder = ['.' fsep];
end
else
opt.relative = 1;
opt.rfolder = oval;
end;
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -