# backup

## PURPOSE

## SYNOPSIS

function backup(or_dir,varargin)

## DESCRIPTION

    backup(or_dir,bk_dir,warn,flags,mode)

    Function for backing up directories by copying only the files that has been
    modified. This is a simple wrapper call to the XCOPY DOS command with some default flags.

    or_dir -(string) original directory to back-up
    bk_dir -(string) back-up (destination) directory
    warn   -(logical) If true (default) will comfirm the user if the source and
             destination directories are correct
    flags  -(string) Flags to XCOPY command. Default is: '/M /E /F /Y /D /H'
    mode   -(string) Determines the operation mode. Options are:
            'xcopy'  : (default) will call xcopy DOS command with respective flags
            'prune'  : calls xcopy command and then delete files in the backup directry that
                         do not exist in the original directory
            'sync'   : syncs both directories. BOTH directories are backep up with the most
                         up-to-date files from either directory.
            'find'   : find files and foders in the backup directory that do not exist in the original directory
            'arch'   : set the archive attribute to ON of files in the original directory that do not exist
                         on the back-up directory

     IMPORTANT NOTE: for the 'prune' method, deleting files in the backup
     that does not exist  the original file will not go to recycling bin unless
     you change the default MATLAB setting.
     To set the recycle state for all MATLAB sessions, use the Preferences
     dialog box. Open the Preferences dialog and select General. To enable or
     disable recycling, click Move files to the recycle bin or Delete files
     permanently. See General Preferences for MATLAB in the Desktop Tools and
     Development Environment documentation for more information.

     Possible Flag optinos are (Windows 2000 and XP ) this will overwrite default flags:

     /A Copies only files with the archive attribute set, doesn't change the attribute.
     /M Copies only files with the archive attribute set, turns off the archive attribute.
     /D:m-d-y Copies files changed on or after the specified date. If no date is given, copies only those files whose source time is newer than the destination time.
     /EXCLUDE:file1 [+file2][+file3]... Specifies a list of files containing strings. When any of the strings match any part of the absolute path of the file to be copied, that file will be excluded from being copied. For example, specifying a string like \obj\ or .obj will exclude all files underneath the directory obj or all files with the .obj extension respectively.
     /P Prompts you before creating each destination file.
     /S Copies directories and subdirectories except empty ones.
     /E Copies directories and subdirectories, including empty ones. Same as /S /E. May be used to modify /T.
     /V Verifies each new file.
     /W Prompts you to press a key before copying.
     /C Continues copying even if errors occur.
     /I If destination does not exist and copying more than one file, assumes that destination must be a directory.
     /Q Does not display file names while copying.
     /F Displays full source and destination file names while copying.
     /L Displays files that would be copied.
     /H Copies hidden and system files also.
     /R Overwrites read-only files.
     /T Creates directory structure, but does not copy files. Does not include empty directories or subdirectories. /T /E includes empty directories and subdirectories.
     /U Copies only files that already exist in destination.
     /K Copies attributes. Normal Xcopy will reset read-only attributes.
     /N Copies using the generated short names.
     /O Copies file ownership and ACL information.
     /X Copies file audit settings (implies /O).
     /Y Suppresses prompting to confirm you want to overwrite an existing destination file.
     /-Y Causes prompting to confirm you want to overwrite an existing destination file.
     /Z Copies networked files in restartable mode

     %Example this will back-up your work directory (without changing the archive attribute)!!!
     bk_dir=[matlabroot,'\backup'];
     or_dir=[matlabroot,'\work'];
     backup(or_dir,bk_dir,[],'/a /y');

## CROSS-REFERENCE INFORMATION

This function calls:

- backup

This function is called by:

- backup

## SUBFUNCTIONS

- function folderfind(or_dir,bk_dir,cond)
- function filefind(or_dir,bk_dir,cond)
- function [fnames,Nfiles]=getfiles(buf_dir)
- function [fnames,Nfolder]=getfolders(buf_dir)

## SOURCE CODE

    0001 function backup(or_dir,varargin)
    0002 %
    0003 %backup(or_dir,bk_dir,warn,flags,mode)
    0004 %
    0005 %
    0006 %Function for backing up directories by copying only the files that has been
    0007 %modified. This is a simple wrapper call to the XCOPY DOS command with some default flags.
    0008 %
    0009 %or_dir -(string) original directory to back-up
    0010 %bk_dir -(string) back-up (destination) directory
    0011 %warn   -(logical) If true (default) will comfirm the user if the source and
    0012 %         destination directories are correct
    0013 %flags  -(string) Flags to XCOPY command. Default is: '/M /E /F /Y /D /H'
    0014 %mode   -(string) Determines the operation mode. Options are:
    0015 %        'xcopy'  : (default) will call xcopy DOS command with respective flags
    0016 %        'prune'  : calls xcopy command and then delete files in the backup directry that
    0017 %                     do not exist in the original directory
    0018 %        'sync'   : syncs both directories. BOTH directories are backep up with the most
    0019 %                     up-to-date files from either directory.
    0020 %        'find'   : find files and foders in the backup directory that do not exist in the original directory
    0021 %        'arch'   : set the archive attribute to ON of files in the original directory that do not exist
    0022 %                     on the back-up directory
    0023 %
    0024 %
    0025 % IMPORTANT NOTE: for the 'prune' method, deleting files in the backup
    0026 % that does not exist  the original file will not go to recycling bin unless
    0027 % you change the default MATLAB setting.
    0028 % To set the recycle state for all MATLAB sessions, use the Preferences
    0029 % dialog box. Open the Preferences dialog and select General. To enable or
    0030 % disable recycling, click Move files to the recycle bin or Delete files
    0031 % permanently. See General Preferences for MATLAB in the Desktop Tools and
    0032 % Development Environment documentation for more information.
    0033 %
    0034 %
    0035 % Possible Flag optinos are (Windows 2000 and XP ) this will overwrite default flags:
    0036 %
    0037 % /A Copies only files with the archive attribute set, doesn't change the attribute.
    0038 % /M Copies only files with the archive attribute set, turns off the archive attribute.
    0039 % /D:m-d-y Copies files changed on or after the specified date. If no date is given, copies only those files whose source time is newer than the destination time.
    0040 % /EXCLUDE:file1 [+file2][+file3]... Specifies a list of files containing strings. When any of the strings match any part of the absolute path of the file to be copied, that file will be excluded from being copied. For example, specifying a string like \obj\ or .obj will exclude all files underneath the directory obj or all files with the .obj extension respectively.
    0041 % /P Prompts you before creating each destination file.
    0042 % /S Copies directories and subdirectories except empty ones.
    0043 % /E Copies directories and subdirectories, including empty ones. Same as /S /E. May be used to modify /T.
    0044 % /V Verifies each new file.
    0045 % /W Prompts you to press a key before copying.
    0046 % /C Continues copying even if errors occur.
    0047 % /I If destination does not exist and copying more than one file, assumes that destination must be a directory.
    0048 % /Q Does not display file names while copying.
    0049 % /F Displays full source and destination file names while copying.
    0050 % /L Displays files that would be copied.
    0051 % /H Copies hidden and system files also.
    0052 % /R Overwrites read-only files.
    0053 % /T Creates directory structure, but does not copy files. Does not include empty directories or subdirectories. /T /E includes empty directories and subdirectories.
    0054 % /U Copies only files that already exist in destination.
    0055 % /K Copies attributes. Normal Xcopy will reset read-only attributes.
    0056 % /N Copies using the generated short names.
    0057 % /O Copies file ownership and ACL information.
    0058 % /X Copies file audit settings (implies /O).
    0059 % /Y Suppresses prompting to confirm you want to overwrite an existing destination file.
    0060 % /-Y Causes prompting to confirm you want to overwrite an existing destination file.
    0061 % /Z Copies networked files in restartable mode
    0062 %
    0063 % %Example this will back-up your work directory (without changing the archive attribute)!!!
    0064 % bk_dir=[matlabroot,'\backup'];
    0065 % or_dir=[matlabroot,'\work'];
    0066 % backup(or_dir,bk_dir,[],'/a /y');
    0067
    0068
    0069
    0070 home_dir=pwd;
    0071 bk_dir=varargin{1};  %second input is the directory to which we wish to backup
    0072 warn=1;
    0073 flags=' /M /E /F /Y /D /H';
    0074 mode='xcopy';
    0075
    0076 if(nargin >= 3 )
    0077     if(~isempty(varargin{2}))
    0078         warn=varargin{2}; %overwrite warning flag if not called by empty brackets
    0079     end
    0080     if(nargin >=4)
    0081         if(~isempty(varargin{3}))
    0082             flags=varargin{3};
    0083         end
    0084         if(nargin== 5)
    0085             mode=varargin{4};
    0086         end
    0087     end
    0088 end
    0089
    0090 %Display message to make sure function was called correctly
    0091
    0092 if(strcmp(mode,'xcopy'))
    0093     try
    0094         cd(bk_dir)
    0095     catch
    0096         str=['Backup directory: \n\n',bk_dir,'\n\nDoes not exist, create one (Y/N)?: '];
    0097         resp=input(str,'s');
    0098         if(strcmpi(resp,'y'))
    0099             [sucess]=mkdir(bk_dir);
    0100             if(~sucess)
    0101                 warning('Could not generate backup directory, please check writing status.')
    0102                 return
    0103             end
    0104         else
    0105             warning('Unable to continue due to non-existing backup directory.')
    0106             return
    0107         end
    0108     end
    0109     cd(home_dir)
    0110
    0111     if(warn)
    0112         str=['***Backing-up data FROM: \n\n',or_dir,'\n\n***TO:\n\n',bk_dir,'\n\n***Please confirm (Y/N): '];
    0113         resp=input(str,'s');
    0114
    0115         if(strcmpi(resp,'Y'))
    0116             fprintf('\n\n*****Starting backup*****')
    0117         else
    0118             warning('Quitting backup')
    0119             return
    0120         end
    0121     else
    0122         str=['***Backing-up data FROM: \n\n',or_dir,'\n\n***TO:\n\n',bk_dir,'\n\n***'];
    0123         fprintf(str)
    0124     end
    0125     %Call XCOPY command
    0126     str=['!xcopy "',or_dir,'" "',bk_dir,'" ',flags];
    0127     tic
    0128     eval(str)
    0129     t=toc;
    0130     fprintf(['***Backup complete in ', num2str(t/60),' minutes.\n']);
    0131
    0132 else %%%% In non xcopy modes
    0133
    0134     switch lower(mode)
    0135         case 'prune'
    0136             cond='del';
    0137             %back-up files first for prune mode
    0138             backup(or_dir,bk_dir,warn,flags,'xcopy')
    0139             fprintf('***Removing files in:\n');
    0140             display(bk_dir)
    0141             fprintf('\n***That do not exist in :\n');
    0142             display(or_dir)
    0143             fprintf('\n');
    0144             resp=input('Ok (Y/N): ','s');
    0145             if(~strcmpi(resp,'y'))
    0146                 warning('Operation cancelled.')
    0147                 return
    0148             end
    0149         case 'find'
    0150             cond='src';
    0151             %need to swap names under these conditions due to
    0152             %the order of the for loops in helper functions...
    0153             tmp=or_dir;
    0154             or_dir=bk_dir;
    0155             bk_dir=tmp;
    0156             fprintf('***Searching for files in:\n');
    0157             display(bk_dir)
    0158             fprintf('\n***That do not exist in :\n');
    0159             display(or_dir)
    0160             fprintf('\n');
    0161         case 'arch'
    0162             cond='arch';
    0163             %need to swap names under these conditions due to
    0164             %the order of the for loops in helper functions...
    0165             tmp=or_dir;
    0166             or_dir=bk_dir;
    0167             bk_dir=tmp;
    0168             fprintf('***Archiving files & folders in:\n');
    0169             display(bk_dir)
    0170             fprintf('\n***That do not exist in :\n');
    0171             display(or_dir)
    0172             fprintf('\n');
    0173         case 'sync'
    0174             flags=['/E /F /Y /D /H'];
    0175             fprintf('***Syncing***Backing up only the most recent files in both directories.\n')
    0176             fprintf('\t Hit enter to continue or ctrl+c to quit.')
    0177             pause
    0178             backup(or_dir,bk_dir,warn,flags,'xcopy')
    0179             backup(bk_dir,or_dir,warn,flags,'xcopy')
    0180             return %exit function from sync mode
    0181     end
    0182
    0183
    0184     tic;
    0185     %Call helper functions. Implements recursion until a modified sub-folder is
    0186     %found that does not have any directories inside and manipulates accordingly the files
    0187     folderfind(or_dir,bk_dir,cond);
    0188     t=toc;
    0189     fprintf(['*****Complete in ' num2str(t/60), ' minutes.****\n\n'])
    0190
    0191 end
    0192
    0193
    0194
    0195
    0196
    0197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0198 %%% Helper function that backs up only folders within a directory
    0199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0200
    0201 function folderfind(or_dir,bk_dir,cond)
    0202
    0203
    0204 %CD into original and back-up directories and get all file names
    0205 [or_fnames,or_Nfolders]=getfolders(or_dir);
    0206 [bk_fnames,bk_Nfolders]=getfolders(bk_dir);
    0207
    0208
    0209 %End of recursion, leaf of the tree, so delete any files in this folder
    0210 %that does not exist in original directory
    0211 filefind(or_dir,bk_dir,cond);
    0212
    0213 if(bk_Nfolders>0)
    0214
    0215     %More subfolders inside. Keep going down the tree searching for
    0216     %folder & files non-existent in orginal directory
    0217
    0218     % Loop through all folders & files and move only those that do not exist
    0219     for i=1:bk_Nfolders
    0220         match=0;
    0221         for j=1:or_Nfolders
    0222             match=strcmp(or_fnames(j).name,bk_fnames(i).name);
    0223             if(match)
    0224                 %Folder exists in original directory
    0225                 %move in a directory deeper
    0226                 or_folder=[or_dir,'/',or_fnames(j).name];
    0227                 bk_folder=[bk_dir,'/',bk_fnames(i).name];
    0228                 folderfind(or_folder,bk_folder,cond);
    0229                 break %from the original directory search since folder was found
    0230             end
    0231         end %of search through the original directory
    0232
    0233         if(~match)
    0234             %No matching folder was found so apply cond
    0235             bk_folder=[bk_dir,'\',bk_fnames(i).name];
    0236             if(strcmp(cond,'del'))
    0237
    0238                 %Prompt before user deleting
    0239                 fprintf('\n Delete folder: \n')
    0240                 disp(bk_folder)
    0241                 fprintf('\n')
    0242                 resp=input('(Y/N): ','s');
    0243                 if(~strcmpi(resp,'y'))
    0244                     warning('Operation cancelled.')
    0245                     return
    0246                 end
    0247                 dir_sucess=rmdir(bk_folder,'s'); %remove directory
    0248
    0249                 if(~dir_sucess)
    0250                     str=['Error deleting folder in: ', bk_folder,' . Check permission status.'];
    0251                     warning(str)
    0252                 else
    0253                     fprintf('\t**Folder deleted: \n')
    0254                     disp(bk_folder)
    0255                 end
    0256
    0257             elseif(strcmp(cond,'arc'))
    0258                 fprintf('\t**Unique folder set to archive : \n')
    0259                 fileattrib(bk_folder,'+a')%set for archiving
    0260                 disp(bk_folder)
    0261             elseif(strcmp(cond,'src'))
    0262                 fprintf('\t**Unique folder: \n')
    0263                 disp(bk_folder)
    0264             else
    0265                 %reserved for later
    0266             end
    0267
    0268         end %End of no match
    0269
    0270
    0271
    0272     end  %End of browsing through the backup directory
    0273 end %End of recursion conditions
    0274
    0275
    0276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0277 %%% Helper function that backs up only files within a directory
    0278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0279 function filefind(or_dir,bk_dir,cond)
    0280
    0281
    0282 %CD into original and back-up directories and get all file names
    0283 [or_fnames,or_Nfiles]=getfiles(or_dir);
    0284 [bk_fnames,bk_Nfiles]=getfiles(bk_dir);
    0285
    0286 % Loop through all files delete only those that do not exist in original
    0287 for i=1:bk_Nfiles
    0288     match=0;
    0289     for j=1:or_Nfiles
    0290         match=strcmp(or_fnames(j).name,bk_fnames(i).name);
    0291         if(match)
    0292             break %file found so exit search
    0293         end
    0294     end %of original directory search
    0295
    0296     if(match==0)
    0297         %No file was found son manipulate accordin to cond
    0298         bk_file=[bk_dir,'\',bk_fnames(i).name];
    0299         if(strcmp(cond,'del'))
    0300
    0301             %Prompt before user deleting
    0302             fprintf('\n Delete file: \n')
    0303             disp(bk_file)
    0304             fprintf('\n')
    0305             resp=input('(Y/N): ','s');
    0306             if(~strcmpi(resp,'y'))
    0307                 warning('Operation cancelled.')
    0308                 return
    0309             end
    0310
    0311
    0312             delete(bk_file);
    0313             disp(['***Backup file deleted: ',bk_file])
    0314         elseif(strcmp(cond,'arc'))
    0315             disp(['***Unique file set to archive: ',bk_file])
    0316             fileattrib(bk_file,'+a')%set for archiving
    0317         elseif(strcmp(cond,'src'))
    0318             disp(['***Unique file: ',bk_file])
    0319         else
    0320             %reserved for later
    0321         end
    0322         fprintf('\n')
    0323     end
    0324 end
    0325
    0326
    0327
    0328
    0329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0330 %%%%%Helper function to get only files with no folders
    0331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0332 function [fnames,Nfiles]=getfiles(buf_dir)
    0333 home_dir=pwd;
    0334 cd(buf_dir)
    0335 fnames=dir;
    0336 Nfiles=length(fnames);
    0337
    0338 %Search and delete folder names from compiled list
    0339 i=1;
    0340 while(i <= Nfiles)
    0341     if(fnames(i).isdir)
    0342         fnames(i)=[]; %delete any directories or folders from search
    0343         Nfiles=Nfiles-1;
    0344     else
    0345         i=i+1;
    0346     end
    0347 end
    0348
    0349 cd(home_dir)
    0350
    0351
    0352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0353 %%%%%Helper function to get only folders (no files in the comiled list)
    0354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    0355 function [fnames,Nfolder]=getfolders(buf_dir)
    0356 home_dir=pwd;
    0357 cd(buf_dir)
    0358 fnames=dir;
    0359 Nfolder=length(fnames);
    0360
    0361 %Search and delete files names from compiled list
    0362 i=1;
    0363 while(i <= Nfolder)
    0364     if(~fnames(i).isdir || strcmp(fnames(i).name,'.') || strcmp(fnames(i).name,'..'))
    0365         fnames(i)=[]; %delete any files from search
    0366         % . and .. directories
    0367         Nfolder=Nfolder-1;
    0368     else
    0369         i=i+1;
    0370     end
    0371 end
    0372
    0373 cd(home_dir)
    0374
    0375
    0376
    0377
    0378
    0379
    0380
    0381
    0382