Code covered by the BSD License  

Highlights from
aselfpack

image thumbnail
from aselfpack by Durga Lal Shrestha
Creation of self-extract packages with file filters.

aselfpack(sourceDir,filt,packName,packTitle,packDescription,installNotes)
function aselfpack(sourceDir,filt,packName,packTitle,packDescription,installNotes)
% ASELFPACK  Creats self-extract package.
% Creates a single matlab self-extract p file with all the contents of a 
% selected folder(including subdirectories) based on the filter FILT.                       
%                                             
% USAGE:
%  ASELFPACK(sourceDir,filt,packName,packTitle,packDescription,installNotes)
%                                                   
% INPUT:
%   sourceDir - Source directory to be packed                                   
%   filt -  string or cell array of string for filtering the files of source directory
%           during packing. 
%           The typical form of valid filter:
%           '~.m' - exclude all m files
%           '*.m' - include all m files
%           '*.*' - include all files (default)
%           {'*.m' ,'*.p'} - include only m files and p files
%           {'~.m' ,'~.asv'} - exclude m and asv files
%           {'~.m', '~.asv','demo.m'} - exclude all m and asv files except demo.m
%           {'*.m' ,'~demo.m'} - include all m files except demo.m
%
%   packName -        Filename of the self extracting package [ 'self' ] 
%   packTitle -       Title of the self extracting package
%                     [ '<main folder> MATLAB Toolbox' ]
%   packDescription - Information to be added in self extracting package,
%                     cell array [ <none> ]
%   installNotes -    Installation notes to be shown at the end of the
%                     extraction, cell array [ <none> ]
%           
% OUTPUT:                                
%        
% EXAMPLES: 
%      sourceDir      = 'd:\My Matlab Tools\Mytoolbox';
%      filt           = {'~.m', '~.asv','demo.m'}
%      packName      = 'mytoolbox_install';
%      packTitle       = 'My analysis toolbox';
%      packDescription = {'lots of files...','to do whatever...'};
%      installNotes   = {'just install... and ';'if you have doubts';
%      'write me to mail@mail.m'};
%  ASELFPACK(sourceDir,filt,packName,packTitle,packDescription,installNotes)
%      
% See also: SELFPACK, RPCODE
%
% NOTES:
% This ASELFPACK is improvement of the orginal submission SELFPACK 
% by martinho@fis.ua.pt
% (http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=8565
%
% ADITIONAL FUNCTIONALITY compared to SELFPACK
% 1. Filter to exclude or include some files
% 2. Add folders to Matlab search path
% 3. User defined folder for installation
% HISTORY
% 1.0.0 - Initial release 16-Oct-2008
% 1.1.0 (27-Jan-2009)
%  - Source directory is not created any more in the installation directory
%  - Corrected double path separator
%  - Private directory is not added to the path
% 1.2.0 (09-Nov-2009)
%  - Bug fixed in filter
% ToDo
%  

% Author: Durga Lal Shrestha
% UNESCO-IHE Institute for Water Education, Delft, The Netherlands
% eMail: durgalal.shrestha@gmail.com
% Website: www.durgalal.co.cc
% Copyright 2008-2009 Durga Lal Shrestha.
% $First created: : 16-Oct-2008
% $Revision: 1.2.0 $ $Date: 09-Nov-2009 13:55:49 $

% ***********************************************************************
%%
useTextAsBin = 1;
createPfile  = 1;
pRemoveMFile = 0;

if nargin < 1
  disp(':: you must input a folder name')
  return
elseif ~exist(sourceDir,'dir')
  disp(':: the selected folder do not exist')
  return
end
% %deal with filesep:
sourceDir = strrep(sourceDir,'/',filesep);
sourceDir = strrep(sourceDir,'\',filesep);
%sourceDir = strrep(sourceDir,':',filesep); % Changed by DLS
sourceDir = realpath(sourceDir);

% find the main folder (remove extra path):
lastDir = basename(sourceDir);
%thePath = dirname(sourceDir);
thePath = sourceDir;

if nargin < 2 || isempty(filt)
	filt = {'*.*'};
end
	
if nargin < 3
  packName = 'self.m';
else
  packName = [packName,'.m'];
end

if nargin < 4
  packTitle   = [lastDir,' MATLAB Toolbox'];
end

if nargin < 5
  packDescription = {};
end

if nargin < 6
  installNotes = {};
end

% check the output file:
mFile = packName;
pFile = [packName(1:end-1),'p'];
if createPfile
  finalFile = pFile;
else
  finalFile = mFile;
end

if exist([pwd,filesep,finalFile],'file') || exist([pwd,filesep,mFile],'file')
  if exist([pwd,filesep,mFile],'file') && createPfile
    fprintf(1,'\n :: Warning: the self-extract installation file %s will be overwritten !!\n',mFile);
  end
  fprintf(1,'\n :: Warning: the self-extract installation file %s already exist\n',finalFile);
  while 1
    yesno = input('\n  Do you want to continue ([y],n) ? ','s');
    if isempty(yesno) || isequal(yesno,'y')
      break
    elseif isequal(yesno,'n')
      fprintf(1,'\n opperation canceled\n\n');
      return
    end
  end
  fprintf(1,'\n')
end

% get all available subdirs and number of files:
dirs   = get_dirs(sourceDir);
nfiles = get_nfiles(dirs);

if nfiles > 0
  fprintf(1,'\n%s\n',' ---------------------------------------------------');
  fprintf(1,'%s\n',' MATLAB Utility: Self extractor');
  fprintf(1,' %s\n',packTitle);
  for i=1:length(packDescription)
    fprintf(1,' %s\n',packDescription{i});
  end
  fprintf(1,'\n')
  fprintf(1,'   :: Source directory %s\n',sourceDir);
  fprintf(1,'   :: found %d folder\n',length(dirs));
  fprintf(1,'   :: found %d files\n',nfiles);
else
  disp(':: there are no files to process')
  return
end

% add first lines:
process_init(packName,packTitle,packDescription);

% add folders:
process_folders(dirs,packName,packTitle,packDescription,thePath);

% add files:
[numok,numbad] = process_files(dirs,filt,packName,useTextAsBin,thePath);

% add final lines:
process_final(packName,installNotes);

% add functions:
process_funcs(packName);

% create p file and delete the m file:

if createPfile
  pcode([pwd,filesep,packName]);
  if pRemoveMFile
    delete([pwd,filesep,packName]);
  end
end

% show size of the output file:
d  = dir(finalFile);
nb = d.bytes;
fprintf(1,'\n   :: done --  Self-extraction file %s (%d bytes)\n',finalFile,nb);
fprintf(1,  '   :: number of files added     = %d\n',numok);
fprintf(1,  '   :: number of files NOT added(due to filtering or error) = %d\n',nfiles-numbad-numok);
%fprintf(1,'\n   :: the installation folder is %s\n',lastDir);
fprintf(1,'%s\n\n',' ---------------------------------------------------');

% --------------------------------------------------------------------

function process_init(output,title,description)
fid=fopen(output,'w');

% function line:
fprintf(fid,'function %s\n',output(1:end-2));

% first line:
fprintf(fid,'%%%s',upper(output(1:end-2)));
fprintf(fid,'%s %s\n','   Installer of the',title);

% description:
for i=1:length(description)
  fprintf(fid,'%%   %s\n',description{i});
end

% more info:
fprintf(fid,'%%\n%s\n','%   This is a self extraction file which will create the toolbox');
fprintf(fid,'\n');
fprintf(fid,'%%   Ceated in %s\n',datestr(now));
fprintf(fid,'%%   by the utility %s from Durga Lal Shrestha, durgals@hotmail.com\n',upper(mfilename));
fprintf(fid,'\n');
fclose(fid);

% --------------------------------------------------------------------

function withErrors = process_folders(dirs,output,title,description,thePath)
fid = fopen(output,'a');


for i=1:length(dirs)
  % first I need to remove the extra path so that only the last dir remains:
  dirs{i} = strrep(dirs{i},thePath,'');
  %dirs{i}=dirs{i}(2:end);% DLS
  % find if there is filesep at the begining and remove it
  k = strfind(dirs{i}, 'filesep');
  if ~isempty(k) && k(1)==3
      dirs{i}=dirs{i}(k(1)+7+2:end);
  end
  fprintf(fid,'%s%d%s%s%s\n','dirs(',i,') = {[''',dirs{i},''']};');
end

fprintf(fid,'\n');
%fprintf(fid,'%s\n','% theMainDir = dirs{1};');

% show title and descripton:
fprintf(fid,'%s\n','fprintf(1,''\n ---------------------------------------------------\n'');');
fprintf(fid,'%s\n','fprintf(1,'' Installation of the matlab toolbox:\n'');');
fprintf(fid,'%s\n', ['fprintf(1,'' %s\n'',''',title,''');']);
for i=1:length(description)
  fprintf(fid,'%s\n', ['fprintf(1,'' %s\n'',''',description{i},''');']);
end

%% Installation folder
% Added this functionality to the orginal submission by Durga Lal Shrestha
fprintf(fid,'%s\n','fprintf(1,'' %s\n'','''');');
fprintf(fid,'%s\n', 'fprintf(1,''\n :: Select directory to install, press any key to open directory selector\n\n'');');
fprintf(fid,'%s\n', '  pause');
fprintf(fid,'%s\n','install_dir = uigetdir(pwd,''Select directory to install files'');');
fprintf(fid,'%s\n','if isequal(install_dir,0)');
fprintf(fid,'%s\n','  install_dir = pwd;');
fprintf(fid,'%s\n','end');

%% ask if want to continue:
fprintf(fid,'%s\n', 'fprintf(1,''\n The installation will copy files to the folder %s\n'',install_dir);');
fprintf(fid,'%s\n', 'fprintf(1,''\n Warning: the folders may not be empty and new files will overwrite existing ones\n\n'');');
fprintf(fid,'\n');
fprintf(fid,'%s\n', 'yesno = input(''\n  Do want to continue ([y],n) ? '',''s'');');
fprintf(fid,'%s\n', 'if isequal(yesno,''n'')');
fprintf(fid,'%s\n', '   fprintf(1,''\n installation canceled\n\n'');');
fprintf(fid,'%s\n', '   return');
fprintf(fid,'%s\n', 'end');

% create all folders:
fprintf(fid,'\n');
fprintf(fid,'%s\n','withErrors = 0;');
fprintf(fid,'%s\n','for i=1:length(dirs)');
fprintf(fid,'%s\n','completePath = [install_dir,filesep,dirs{i}];');	
fprintf(fid,'%s\n','  if ~exist(completePath,''dir'')');
fprintf(fid,'%s\n','    fprintf(1,''   creating folder %s'',completePath);');
fprintf(fid,'%s\n','    try');
fprintf(fid,'%s\n','      mkdir(completePath);');
fprintf(fid,'%s\n','      fprintf(1,''\n'');');
fprintf(fid,'%s\n','    catch');
fprintf(fid,'%s\n','      fprintf(1,'' -- ERROR\n'')');
fprintf(fid,'%s\n','      withErrors = 1;');
fprintf(fid,'%s\n','    end');
fprintf(fid,'%s\n','  else');
fprintf(fid,'%s\n','    %fprintf(1,''   the folder %s already exist\n'',completePath);');
fprintf(fid,'%s\n','  end');
fprintf(fid,'%s\n','end');

%% Add path
% Added this functionality to the orginal submission by Durga Lal Shrestha
fprintf(fid,'%s\n','%% Add path;'); 
fprintf(1,'\n')   
fprintf(fid,'%s\n','yesno = input(''\n    Do you want to add above directories to MATLAB Path ([y],n) ? '',''s'');');
fprintf(fid,'%s\n','if isequal(yesno,''y'')');
fprintf(fid,'%s\n','% Add path;'); 
fprintf(fid,'%s\n','  for i=1:length(dirs);');
fprintf(fid,'%s\n','    completePath = [install_dir,filesep,dirs{i}];');
fprintf(fid,'%s\n','    k=strfind(completePath, ''private'');');  
fprintf(fid,'%s\n','    if isempty(k);');      
fprintf(fid,'%s\n','       addpath(completePath);');
fprintf(fid,'%s\n','    end');
fprintf(fid,'%s\n','  end');
fprintf(fid,'%s\n','  fprintf(1,''\n   The directories have been added to MATLAB search path\n\n'');');
fprintf(fid,'%s\n','else');
fprintf(fid,'%s\n','  fprintf(1,''\n Paths have not been added, you can add manualy via File\Set Path... \n\n'');');
fprintf(fid,'%s\n','end');
fclose(fid);

% --------------------------------------------------------------------

function [numFilesOK,numFilesBAD] = process_files(dirs,filt,output,useTextAsBin,thePath)
fid = fopen(output,'a');

% find the main folder (remove extra path):
subDirs = dirs;
for nd=1:length(dirs)
  %subDirs{nd}(1:length(thePath)+1) = '';
subDirs{nd}(1:length(thePath)) = '';
end

numFilesOK  = 0;
numFilesBAD = 0;
for i=1:length(dirs)
    str=['currentDir=[''',dirs{i},'''];'];
    eval(str);
    str=['currentShownDir=[''',subDirs{i},'''];'];
    eval(str);
    fprintf(1,'   entering in folder %s\n',currentShownDir);
    d=dir(currentDir);
    isd     = zeros(size(d));
    nisnull = zeros(size(d));
    for n=1:length(d)
        isd(n)     = d(n).isdir;  % is dir
        nisnull(n) = d(n).bytes;  % not is null
    end
    % the nisnull condition is needed when dirs are chmod -x
    files   = {d(~isd&nisnull).name};
    folders = {d(~~isd).name};

    if isempty(files) && length(folders) == 2
        fprintf(1,'   the folder %s IS EMPTY\n',currentDir);
    end


    %% Apply filter
    %filt={'~.m' '~.p'};

    for n=1:length(files)
        if applyfilter(files{n},filt)  % Added this functionality to the    
%                                      orginal submission 
            currentFile = files{n};
            fprintf(1,'        processing file %s\n',currentFile);

            theFile = [currentDir,filesep,currentFile];

            % check file type:
            [isbin,type] = isbinary(theFile);

            if ~isempty(isbin)
                f=fopen(theFile);
                c=fread(f);
                theRealSize=prod(size((c)));
                if ~isbin & ~useTextAsBin
                    c=char(c');
                    c=strrep(c,char(13),'');
                    c=strrep(c,'''','''''');
                    if c(end)==10, c=c(1:end-1); end
                    c=strrep(c,char(10),['\n'');' 10 'fprintf(fid,''%s\n'',''']);
                    c=['fprintf(fid,''%s\n'',''',c,''');'];
                    theType = 'text';
                else
                    c=sprintf('%02x\n',c);
                    c(3:3:end)='';
                    nChar=70;
                    m=floor(length(c)/nChar);
                    tmp='';
                    tmp=reshape(c(1:m*nChar),nChar,m);
                    tmp=tmp';
                    if mod(length(c),nChar)
                        tmp=strvcat(tmp,c(m*nChar+1:end));
                    end
                    tmp(:,2:end+1)=tmp;
                    tmp(:,1)='''';
                    tmp(:,end+1) = '''';
                    tmp(:,end+1) = ',';
                    tmp(:,end+1) = 10;
                    tmp(1,end)=10;
                    c=tmp;
                    theType = 'binary';
                end
                theSize=prod(size((c)));
                if ~isbin & ~useTextAsBin
                    fprintf(fid,'\n');
                    fprintf(fid,'%s\n',['file = [install_dir,''' subDirs{i},''',filesep,''',currentFile,'''];']);
                    fprintf(fid,'%s\n',['[withErrors,fid] = ini_file(file,''',type,''');']);
                    fwrite(fid,c);
                    fprintf(fid,'\n');
                    fprintf(fid,'%s\n','fclose(fid);');
                else
                    fprintf(fid,'\n');
                    fprintf(fid,'%s\n',['file = [install_dir,''' subDirs{i},''',filesep,''',currentFile,'''];']);
                    fprintf(fid,'%s\n',['[withErrors,fid] = ini_file(file,''',type,''');']);
                    fprintf(fid,'%s\n','hex = [');
                    fprintf(fid,'%s',c');
                    fprintf(fid,'%s\n','];');
                    fprintf(fid,'%s\n','finnish_file(fid,hex);');
                end
                f=fclose(f);

                numFilesOK = numFilesOK + 1;
            else
                numFilesBAD = numFilesBAD + 1;
                fprintf(1,'        UNABLE to processing file %s\n',currentFile);
            end % ~isempty(isbin)
        end % if filt
    end
end
fclose(fid);

% --------------------------------------------------------------------

function process_final(output,installNotes)
fid = fopen(output,'a');

fprintf(fid,'\n');

% show install notes:
if ~isempty(installNotes)
  fprintf(fid,'%s\n', 'fprintf(1,''\n'');');
end
for i=1:length(installNotes)
  fprintf(fid,'%s\n', ['fprintf(1,'' %s\n'',''',installNotes{i},''');']);
end

fprintf(fid,'\n');

% show installation finnished:
fprintf(fid,'%s\n', 'if withErrors');
fprintf(fid,'%s\n', '  fprintf(1,''\n installation finnished WITH ERRORS\n\n'')');
fprintf(fid,'%s\n', 'else');
fprintf(fid,'%s\n', '  fprintf(1,''\n installation finished\n'')');
fprintf(fid,'%s\n','   fprintf(1,'' ---------------------------------------------------\n\n'');');
fprintf(fid,'%s\n', 'end');

fclose(fid);

% --------------------------------------------------------------------

function process_funcs(output)
fid = fopen(output,'a');

fprintf(fid,'\n');

fprintf(fid,'%s\n', 'function bin=hex_to_bin(s)');
fprintf(fid,'%s\n', 'c = zeros(1, 256);');
fprintf(fid,'%s\n', 'c(abs(''0''):abs(''9'')) = 0:9;');
fprintf(fid,'%s\n', 'c(abs(''a''):abs(''f'')) = 10:15;');
fprintf(fid,'%s\n', 'hex = double(s);');
fprintf(fid,'%s\n', 'bin = 16*c(hex(1:2:end)) + c(hex(2:2:end));');

fprintf(fid,'\n');

fprintf(fid,'%s\n', 'function [withErrors,fid] = ini_file(file,type)');
fprintf(fid,'%s\n', 'fid=fopen(file,''w'');');
fprintf(fid,'%s\n','if fid == -1');
fprintf(fid,'%s\n','  errstr = '' -- ERROR'';');
fprintf(fid,'%s\n','  withErrors = 1;');
fprintf(fid,'%s\n','else');
fprintf(fid,'%s\n','  errstr='''';');
fprintf(fid,'%s\n','  withErrors = 0;');
fprintf(fid,'%s\n','end');
fprintf(fid,'%s\n','if isempty(type)');
fprintf(fid,'%s\n',['  fprintf(1,''       adding file %s%s\n'',file,errstr)']);
fprintf(fid,'%s\n','else');
fprintf(fid,'%s\n',['  fprintf(1,''       adding file %s (%s)%s\n'',file,type,errstr)']);
fprintf(fid,'%s\n','end');

fprintf(fid,'\n');

fprintf(fid,'%s\n', 'function finnish_file(fid,hex)');
fprintf(fid,'%s\n','if fid~=-1');
fprintf(fid,'%s\n','  hex=reshape(hex'',1,prod(size(hex)));');
fprintf(fid,'%s\n','  hex=strrep(hex,'' '','''');');
fprintf(fid,'%s\n','  bin=hex_to_bin(hex);');
fprintf(fid,'%s\n','  fwrite(fid,bin);');
fprintf(fid,'%s\n','  fclose(fid);');
fprintf(fid,'%s\n','end');

fclose(fid);

% --------------------------------------------------------------------

function [dirs,n]=get_dirs(current,dirs)
if nargin < 2, dirs = {current}; end
n=length(dirs);
str = ['d=dir([''',current,''']);'];
eval(str);
for i=1:length(d)
  cdir=d(i);
  if cdir.isdir==1 & ~isequal(cdir.name,'..') & ~isequal(cdir.name,'.')
    n=n+1;
    dirs{n}=[current,''',filesep,''',cdir.name];
    [dirs,n]=get_dirs(dirs{n},dirs);
  end
end

% --------------------------------------------------------------------

function nfiles=get_nfiles(dirname)
nfiles = 0;
for i=1:length(dirname)
  str=['d=dir([''',dirname{i},''']);'];
  eval(str);
  isd     = zeros(size(d));
  nisnull = zeros(size(d));
  for n=1:length(d)
    isd(n)     = d(n).isdir;  % is dir
    nisnull(n) = d(n).bytes;  % not is null
  end
  % the nisnull condition is needed when dirs are chmod -x
  files = {d(~isd&nisnull).name};
  nfiles = length(files) + nfiles;
end

% --------------------------------------------------------------------

function [isbin,type]=isbinary(file)
isbin=0;
type='';
fid=fopen(file);
if fid~=-1
  c=fread(fid,1000);
  if any(c==0), isbin = 1; end
  fclose(fid);
  if isbin
    type='binary';
  else
    type='text';
  end
else
  isbin=[];
  type='';
end

% --------------------------------------------------------------------

function output = basename(theFile)
d = realpath(theFile);
[path,name,ext]=fileparts(d);
output = [name,ext];

function output = dirname(theFile)
d = realpath(theFile);
[path,name,ext]=fileparts(d);
output = path;

function output = realpath(thePath)
output = [];
isfile = 0;
if exist(thePath,'file') == 2 & isempty(which(thePath))
  [path,name,ext]=fileparts(thePath);
  thePath =  path;
  isfile = 1;
end
current = cd;
if exist(thePath,'dir') == 7 & ~isempty(dir(thePath))
  cd(thePath);
  output = cd;
  cd(current);
  if isempty(output)
    if isunix, new = filesep; end
    if ispc,   new='C:\';     end
  end
end
if isfile
  output = [output,filesep,name,ext];
end

%%
function flag = applyfilter(filename,filefilt)
% APPLYFILTER returns true if the filename meets the condition given in 
%             the filter filt
%             filename is the name of the file to be checked.
%             filt is the cell array of string to be used as filter
% The form of filter should be like
% '~.m' - exclude all m files
% '*.m' - include all m files
% '*.*' - include all files (default)
% {'*.m' ,'*.p'} - include only m files and p files
% {'~.m' ,'~.p'} - exclude m files and p files
% {'~.m' ,'demo.m'} - exclude all m files except demo.m
% {'*.m' ,'~demo.m'} - include all m files except demo.m
%
% Please note that {'~.m', '*.p'} is equivalent to '*.p'. So such combination
% does not make any sense.
% 
%%
% Check if filt is cell array

if ~iscell(filefilt)
    filt{1}=filefilt;
else
    filt=filefilt;
end
    
flag = false;
filename = lower(filename);
filt =lower(filt);

% If you want to include particular files
tf = ismember(filename, filt); 
% if strcmpi(filt{1},'*.*')||tf   % Corrected in version 1.2.0
% 	flag = true;
% 	return
% end
if tf
	flag = true;
	return
end

% To exclude some files given in filt
tf = ismember(['~' filename], filt); 
if tf
	flag = false;
	return
end

[~, ~, ext] = fileparts(filename) ;

% Make sure that file like read.txt is not included given the filter
% *.* and ~.txt
% Bug fixed in this version 1.2.0. In the previous version if filter *.* is
% there, then it dominates all other filters. This behaviour is corrected.

tf = ismember('*.*', filt); 
if tf
    tmp = ['~' ext];
    tf1 = ismember(tmp, filt); 
    if ~tf1
        flag = true;
        return
    end
end

% Change filter like * ~ ~ to *
newfilt = [];
j=1;
for i=1:length(filt)
	temp = filt{i}(1);      
	if strcmp(temp,'*')
        newfilt{j} = filt{i};
        j=j+1;
    end
end

if isempty(newfilt)
    newfilt=filt;
end
    
for i=1:length(newfilt)
	filtType = newfilt{i}(1);      % Whether filter is to include or exclude
	filtExt = newfilt{i}(2:end);   % Extension of filter
	% Include files
	if strcmp(filtType,'*')
        flag = false;
		if strcmpi(ext,filtExt)
			flag=true;
			return
		end
	% Exclude files
	elseif strcmp(filtType,'~')
        flag = true;
		if strcmpi(ext,filtExt) || strcmpi('.*',filtExt)
			flag=false;
			return
		end
	end
end

Contact us at files@mathworks.com