function res= younger(fname, varargin)
% USAGE: boolean= younger(fname, fname1, fname2, ...)
%
% Check to see if fname has an older modification date than fname1, fname2, ...
%
% Returns true if at least one of the files fname1, fname2 etc. has a more recent
% modification date than fname. Returns false otherwise.
%
% If you find any errors, please let me know! (peder at axensten dot se)
%
% fname: Path (string) to file that might need to be updated.
%
% fnameN: String, or cell array of strings, containing file path(s) to files that fname
% depends upon. If any of these has a modification date that is not older than
% fname's, then fname needs to be updated. If it is 'checkcallers', the modification
% dates of all functions in the calling chain are checked too.
%
% EXAMPLE:
% if(younger(resultfile, indatafile, which('butchread.m'), 'checkcallers'))
% result= do_time_consuming_stuff(indatafile, data);
% save(resultfile 'result');
% else
% result= load(resultfile, 'result');
% end
%
% NOTE: If fname (or all fnameN) doesn't exist, younger returns false.
%
% HISTORY:
% Version 1.0, 2006-04-19.
% Version 1.1, 2006-07-17:
% - Now returns true or false, not a (often empty) list of files.
% Version 1.2, 2006-11-03:
% - Show a much better example.
% Version 1.2, 2007-09-09:
% - A new option, 'checkcallers'. I present, the modification dates of all callers in
% the calling chain are checked too.
%
% Copyright (C) Peder Axensten (peder at axensten dot se), 2006.
% KEYWORDS: update, file date, changed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Default values.
debug= false;
res= false;
datenumber= -Inf;
% Check target file.
if(nargin < 1), error('There must be at least one argument.'); end
if(~ischar(fname)), error('The first argument must be a string.'); end
info= dir(fname);
if(isempty(info))
warning('pax:younger:argcheck', 'No such file found: %s', fname);
end
if(debug), disp(info); end
if(~isempty(info)), datenumber= datenum(info.date); end
% Check the given files.
N= 0;
while(N < length(varargin))
N= N+1;
if(ischar(varargin{N})) % This argument is a string.
if(strcmp('checkcallers', varargin{N})) % We're checking the calling functions too.
thesource= dbstack('-completenames'); % Get the name of the calling function(s)...
if(numel(thesource) >= 2) % ...if there is at least one.
thesource= unique({thesource.file});
varargin= {varargin{:}, thesource{:}};% Add them to the check list.
end
else
info= dir(varargin{N});
if(isempty(info))
warning('pax:younger:argcheck', 'No such file found: %s', varargin{N});
else
if(debug), disp(info); end
res= (~isempty(info) && (datenumber < datenum(info.date)));
if(res), return; end
end
end
elseif(iscellstr(varargin{N})) % This argument is a cell-string.
varargin= {varargin{:}, varargin{N}{:}};
else
warning('pax:younger:argcheck', ...
'Only strings or cell strings as arguments! Argument %d is %s.', ...
N+1, class(varargin{N}));
end
end
end