function [pth, fn] = fwhich(filename, type, search)
%FWHICH Locates files and directories in the MATLAB path.
% [FILEPATH] = FWHICH(FILENAME) returns the full path (FILEPATH) to the
% file or directory FILENAME. FILEPATH includes the path as well as
% the name of the file that was found. If a file name extension is
% given, the search is done for that specific file alone. If no file
% name extension is given, extentions of '.mex' (platform appropriate)
% and '.m' are assumed. Finally, if FILENAME is a directory, the path
% to that directory is returned after any files of the same name.
% Only directories at the bottom of a directory tree are found.
%
% [PTH, FN] = FWHICH(FILENAME) returns the full path (PTH) and file
% name (FN) in separate arguments. If FILENAME is a directory, the
% path to that directory is returned in PTH, and FN is returned as an
% empty string.
%
% [FILEPATH] = FWHICH(FILENAME, FILETYPE, SEARCHOPT) allows more
% control over the files and directories found by FWHICH. The
% following are valid entries for FILETYPE: 'any', 'file', 'dir'. The
% type 'any' will allow searches for either files or directories. The
% types 'file' and 'dir' restrict the search to either files only or
% directories only, respectively. The following are valid entries for
% SEARCHOPT: 'first', 'all'. The 'first' option restricts the search
% to the first item found in the MATLAB path that matches the
% FILENAME. The 'all' option allows the search to proceed through the
% whole MATLAB path finding all occurances of the item FILENAME.
%
% Note that more restrictive searches (using the specific FILETYPEs of
% 'file' and 'dir' and using 'first' as the SEARCHOPT) will result in
% much faster execution speeds for FWHICH. Additionally, execution
% time is decreased if the file name extention is given. Execution
% time can be very long if the complete MATLAB path is searched.
% P. Barnard 1-10-95
% Copyright (c) 1995 The MathWorks, Inc.
% $Revision: 1.1 $ $Date: 1997/02/11 20:50:47 $
% Check the input arguments.
if ~isstr(filename) error('FILENAME must be a string.'), end
if nargin > 1
if nargin > 2
if strcmp(search, 'all')
findall = 1;
else
findall = 0;
end
else
findall = 0;
end
if strcmp(type, 'any')
ftype = 0;
elseif strcmp(type, 'file')
ftype = 1;
else
ftype = 2;
end
else
findall = 0;
ftype = 0;
end
% Get the MATLAB path and set up the machine specific parameters.
pathsep = ':';
filesep = '/';
c = computer;
sys = 'u';
if strcmp(c(1:2),'PC')
pathsep = ';';
filesep = '\';
sys = 'p';
elseif strcmp(c(1:2),'MA')
pathsep = ';';
filesep = ':';
sys = 'm';
elseif isvms
pathsep = ',';
filesep = '.]';
sys = 'v';
end
% Initialize the first row which; is blank.
pthmat = [];
pth = [];
fn = [];
fpth = setstr(zeros(3,1));
ffn = setstr(zeros(3,1));
% For the case where the first file found is all that is necessary.
if (ftype ~= 2 & ~findall & any(filename == '.'))
fid = fopen(filename);
if fid ~= -1
fullpath = fopen(fid); fclose(fid);
if sys(1)=='p'
indx=find(fullpath=='/'); % For PC, make all slashes '\'.
if ~isempty(indx), fullpath(indx) = setstr(ones(1,length(indx))*real('\')); end
end
p = find(fullpath == filesep(length(filesep)));
if isempty(p)
if sys(1)=='v',
fullpath = [cd fullpath];
else
fullpath = [cd filesep(1) fullpath];
end
p = find(fullpath == filesep(length(filesep)));
end
p = max(p);
% Load results up into pth and fn if it is not a directory.
if ~isdir(fullpath)
pth = fullpath(1:p);
fn = fullpath(p+1:length(fullpath));
end
end
% Return the arguments.
if (nargout < 2)
pth = [pth fn];
end
return % End quickly for this case.
end
% Initialize path variables.
allpath = [path pathsep]; % Add pathseps and cd to make searching easier.
% Check to see if cd is already in path, eliminate it, and add cd at beginning.
curdir = cd;
p = findstr(curdir, allpath);
if p
allpath(p:p-1+min(find(allpath(p:length(allpath)) == pathsep))) = [];
end
allpath = [cd pathsep allpath];
% For PC, make all slashes '\'.
if sys(1)=='p'
indx=find(allpath=='/');
if ~isempty(indx), allpath(indx) = setstr(ones(1,length(indx))*real('\')); end
end
% Find all of the path separators.
seps = find(allpath == pathsep);
% Do the following only if files are to be found.
if ftype ~= 2
% Create a strmat for the path.
q = 1;
for r = seps
if sys(1)=='v',
pthmat = str2mat(pthmat,allpath(q:r-1));
else
pthmat = str2mat(pthmat,[allpath(q:r-1) filesep]);
end
q = r + 1;
end;
% Get MEX file extension.
mexstr = mexext;
if findall
% Loop through every path finding files.
[r,c] = size(pthmat);
for i = 2:r % Starts at 2 because the first line is blank.
% Find each occurance of the given filename, .mex, and .m files.
fid = fopen([deblank(pthmat(i,:)) filename]);
mexfid = fopen([deblank(pthmat(i,:)) filename '.' mexstr]);
mfid = fopen([deblank(pthmat(i,:)) filename '.m']);
tmpid = [fid mexfid mfid];
if any(tmpid > 0)
for i = 1:3
if tmpid(i) ~= -1
fullpath = fopen(tmpid(i)); fclose(tmpid(i));
p = find(fullpath == filesep(length(filesep)));
p = max(p);
% Load results up into pth and fn if it is not a directory.
if ~isdir(fullpath)
pth = str2mat(pth,fullpath(1:p));
ln = length(fullpath);
fn = str2mat(fn,fullpath(p+1:ln));
end
end
end
end % end if
end % for loop on pthmat
else
% Find first occurance of the given filename, .mex, and .m files.
fid = fopen(filename);
mexfid = fopen([filename '.' mexstr]);
mfid = fopen([filename '.m']);
tmpid = [fid mexfid mfid];
if any(tmpid > 0)
for i = 1:3
if tmpid(i) ~= -1
fullpath = fopen(tmpid(i)); fclose(tmpid(i));
p = find(fullpath == filesep(length(filesep)));
if isempty(p)
if sys(1)=='v',
fullpath = [cd fullpath];
else
fullpath = [cd filesep fullpath];
end
p = find(fullpath == filesep(length(filesep)));
end
p = max(p);
if ~isdir(fullpath)
fpth(i,1:p) = fullpath(1:p);
ln = length(fullpath);
ffn(i,1:ln-p) = fullpath(p+1:ln);
end
end
end
% Loop through the path to find the 'first' entry.
[r,c] = size(pthmat);
for i = 1:r
if strcmp(deblank(pthmat(i,:)),fpth(1,:))
pth = str2mat(pth,fpth(1,:));
fn = str2mat(fn,ffn(1,:));
elseif strcmp(deblank(pthmat(i,:)),fpth(2,:))
pth = str2mat(pth,fpth(2,:));
fn = str2mat(fn,ffn(2,:));
elseif strcmp(deblank(pthmat(i,:)),fpth(3,:))
pth = str2mat(pth,fpth(3,:));
fn = str2mat(fn,ffn(3,:));
end
end % for
end % if any(tmpid > 0)
end % if findall
end % if ftype ~= 2
% Find directories of name filename (if directories are to be found).
if ftype ~= 1
lfn = length(filename);
if sys(1)=='v', lfn = lfn + 1; end
pp = findstr(filename,allpath);
for i=1:length(pp)
if ( (allpath(pp(i)-1)==filesep(1)) | (sys(1)=='v' & allpath(pp(i)-1)=='[') ) ...
& (allpath(pp(i)+lfn)==pathsep)
if sys(1)=='v',
pth = str2mat(pth, allpath(max(seps.*(seps < pp(i)))+1:pp(i) + lfn-1));
else
pth = str2mat(pth, [allpath(max(seps.*(seps < pp(i)))+1:pp(i) + lfn-1) filesep]);
end
fn = str2mat(fn, []);
if ~findall, break; end
end
end
end
% Removes the first row which; is blank.
if ~isempty(pth) pth(1,:) = []; end
if ~isempty(fn) fn(1,:) = []; end
% Empty pth and fn rows that contain a single blank.
[r,c] = size(pth);
for i = r:-1:1
if isspace(fn(i,:))
fn(i,:) = setstr(zeros(size(fn(i,:))));
end
if isspace(pth(i,:))
pth(i,:) = setstr(zeros(size(pth(i,:))));
end
end
% Return the arguments.
if (nargout < 2)
pth = [pth fn];
end