image thumbnail

Copy Files in Batches using Search Terms

by

 

Copy files matching search terms, from sub-directories matching search terms into a new directory.

accumulator
function accumulator
%Tristan Ursell
%File accumulator
%March 2012
%
%This function is a command line program that copy all the files in a set
%of sub-directories whose file names match a given set of search terms, 
%into a new directory.  The new directory's name can be specified or
%automatically generated.  The copied files will retain their old name
%structure, except the sub-directory name from which they originated will
%be appended onto the name.
%
%Follow the command-line instructions.  File name search terms can not
%include single quotes. Search terms preserve spaces between words, hence
%do not include spaces that are not there, and are case sensitive.
%

%get basal directory
[path1]=uigetdir('','Select the root search directory.');
if path1==0
    return
end

while 1
    subdir=input('Enter sub-directory search term, or <enter> for all sub-directories: ','s');
    if length(subdir)>1
        %get the names that match the single search term
        Dstruct=dir(fullfile(path1,['*' subdir '*']));
    else
        %set the default action
        Dstruct=dir(path1);
    end
    
    %get the indices of the directories that match the search term
    baselist=and([Dstruct.isdir],and(~strcmp('.',{Dstruct.name}),~strcmp('..',{Dstruct.name})));
    dirs=find(baselist);
    
    if isempty(dirs)
        disp('Warning: No directories matched this search.')
    else
        break
    end
end

%inform user how directories were found
disp(' ')
disp(['Found ' num2str(length(dirs)) ' matching directories in the path:'])
disp(path1)
disp(' ')

%get file name search terms from user
searchbase=input('Enter search terms separated by commas: ','s');
disp(' ')

%check to make sure they entered something
if isempty(searchbase)
    error('At least one search term must be specified.')
end

%get new directory name
newdir=input('Enter new directory name, or <enter> for default: ','s');
disp(' ')

%set default directory name
dtstring=datestr(now);
dtstring(or(isspace(dtstring),dtstring==':'))='_';
if and(isempty(newdir),isempty(subdir))
    newdir=['accumulator_' dtstring];
elseif and(isempty(newdir),~isempty(subdir))
    newdir=['accumulator_' dtstring '_' subdir];
end

%make new directory
mkdir(path1,newdir)

%construct list of search terms
commas=find(char(searchbase)==',');
commas=[0,commas,length(char(searchbase))+1];
nterms=length(commas)-1;

%construct all the pathnames and command lines needed to copy files
copy_num=0;
for i=1:length(dirs)
    %construct command and use filefinder to get list of names
    pathname=fullfile(path1,Dstruct(dirs(i)).name);
    exetext=['filefinder(pathname'];
    
    for j=1:nterms
        curr_term=searchbase(commas(j)+1:commas(j+1)-1);
        exetext=[exetext ',''' curr_term ''' '];
    end
    
    exetext=[exetext ');'];
    
    %execute filefinder and get list of names
    tempnames=eval(exetext);
    ncopy=length(tempnames);
    copy_num=copy_num+ncopy;
    
    if ncopy>0
        disp(['Copying ' num2str(ncopy) ' files from: '])
        disp(fullfile(path1,Dstruct(dirs(i)).name))
        disp(' - to - ')
        disp(fullfile(path1,newdir))
        
        for j=1:ncopy
            path_in=fullfile(fullfile(path1,Dstruct(dirs(i)).name),char(tempnames(j)));
            path_out=fullfile(fullfile(path1,newdir),[Dstruct(dirs(i)).name '_' char(tempnames(j))]);
            copyfile(path_in,path_out);
        end
    end
end

if copy_num>0
    disp(' ')
    disp(['A total of ' num2str(copy_num) ' files were copied to the directory: '])
    disp(newdir)
else
    disp(' ')
    disp('No files were copied.')
    rmdir(path1,newdir)
end



function filenames = filefinder(searchpath,varargin)
%Tristan Ursell
%File Finder
%March 2012
%
%filenames = filefinder('searchpath','searchterm1','seartchterm2',...);
%
%This function will return a list of file names that contain all of the
%given search terms.  All entries to this function should be strings.  All
%search terms are case sensitive!
%
%filenames is a cell array.
%
%Conceptual Example:
%
% Let's presume that within 'searchpath' there are, in total, five files:
%
% 1) future.txt
% 2) predictions.txt
% 3) future predictions.txt
% 4) predilections.txt
% 5) predictions for future.txt
%
% Using the search term '.txt' returns a cell array with all five file
% names.
%
% Using the search term 'tions' returns a cell array with filenames 2
% through 5.
%
% Using the serach term 'future' returns a cell array with filenames 1,3,
% and 5.
%
% Using the search terms 'future' and 'prediction' returns a cell array
% with filenames 3 and 5.
% 
% Using the search term 'future prediction' returns a cell array with only
% filename 3. Thus one can combine two independent search terms in an
% ordered search term.


%parse varargin input
nargs=nargin-1;

%create the list of all items in the path
mainstruct=dir(searchpath);

%figure out which items are files (i.e. not directories)
filelist=find(~[mainstruct.isdir]);

%Calculate number of files
nfiles=length(filelist);

%if search terms are given
if nargs>0
    %check each term agains each tile
    checkmat=zeros(nfiles,nargs);
    for i=1:nfiles
        for j=1:nargs
            temp1=strfind(mainstruct(filelist(i)).name,char(varargin{j}));
            checkmat(i,j)=~isempty(temp1);
        end
    end
    %count up the files that contain all the search terms
    sublist=sum(checkmat,2)==nargs;
    %put the names of those files into a cell-array
    filenames={mainstruct(filelist(sublist)).name};
else
    %if no search terms are given, return full list of filenames
    filenames={mainstruct(filelist).name};
end


Contact us