Code covered by the BSD License  

Highlights from
Files to folders based on properties

image thumbnail

Files to folders based on properties

by

 

Groups files into folders based on user defined file properties.

filesPropsFolders=files2filePropsFolders(varargin)
function filesPropsFolders=files2filePropsFolders(varargin) 
% files2filePropsFolders
% Groups files into folder based on user defined file properties.
%  
%% Syntax
%  filesPropsFolders=files2filePropsFolders;
%  filesPropsFolders=files2filePropsFolders( 'inputsList', inputsList );
%  filesPropsFolders=files2filePropsFolders( 'inputsList', inputsList,...
%      'files2filePropsFolders', files2filePropsFolders, 'fileOp', @fileOp,...
%      'flagGUI', flagGUI, 'setInptsSource', setInptsSource,...
%      'browserTitle', browserTitle );
%  
%% Description
% This functions goal is to reorganize the user chosen files into folders. The file are
%   organized based on user defined file property. Each such property results in a folder
%   populated by the files, with such a value of that property. 
%   I've written this function to make the task of arranging my camera photos by their
%   date into appropriate folders automatic. 
%   The function inputs are defined in pairs- "parameter name" followed by parameter value, where
%   parameters ordering is not important. Each parameter can be omitted. In such a case
%   default values will be used.
%  
%% Input arguments (defaults exist):
%     inputsList- a cell array (list) of folders and/or files. A single file, a single
%       folder, or even empty input are also supported. Empty input will results in
%       opening of a files/folders browser.
%   files2filePropsFolders- a string (an array of chars) describing the property according
%       to which files selection is done. This property should be among regular file
%       properties returned by "dir" function, or the relevant properties returned by the
%       relevant file properties query function (see hFuncFileProps).
%   fileOp- a function handle of an operation to be applied to the file. So far only
%       {@movefile, @copyfile} functions were tested.
%   filesFilter- a list (cell array) of extensions describing the file type user wishes to
%       detect.
%   flagGUI-  When enabled allows the user to choose the files list using the
%       Explorer. Note files will be order according to their names (and not the order
%       you've clicked them).
%   setInptsSource- the input files source type- files list a directory or all files
%       located under the directory (including sub-folders). The user must choose one of
%       the three options {'Files list', 'Directory', 'Recursive Directory'}
%   browserTitle- a string used in the files/directories browser menu.
%  
%% Output arguments:
%     filesPropsFolders-    a cell array of folders where files were placed, based on their
%                       property values.
%  
%% Issues & Comments:
%   Files with missing (empty) property values will not be affected. Another easy to
%       implement option is to pace all such files in a predefined folder.
%
%% Example:
% fileNamesList=cat( 1, folderFiles(pwd), {'peppers.png'}, {'rhinos'} );
% foldersList=files2filePropsFolders('inputsList', fileNamesList,...
%     'targetFileProp', 'Height', 'fileOp', @copyfile);
% fprintf('New created directories and files\n');
% for iFolder=1:numel(foldersList)
%     fprintf('\nFolder "%s" files:\n', foldersList{iFolder});
%     filesCell=cellstr( ls(foldersList{iFolder}) );
%     isFolder=( cellfun(@isdir, filesCell, 'UniformOutput', false) );
%     filesCell=filesCell( not(cat( 2, isFolder{:} )) );
%     fprintf( '\t%s\n', filesCell{:} );
% end
% fprintf('\nCleaning up the mess, removing created directories\n');
% [status, message, messageid] = cellfun( @rmdir, foldersList,...
%     repmat({'s'}, size( foldersList )), 'UniformOutput', false );
%
%% See also:
%  - filesListFromInput
%
%% Revision history
% First version: Nikolay S. 2013-04-18.
% Last update:   Nikolay S. 2013-04-21.
%
% *List of Changes:*
%

%% Default user param values
inputsList={};
files2filePropsFolders='date';
fileOp=@copyfile; % {@movefile, @copyfile}
filesFilter=[];
setInptsSource=[];
flagGUI=[];
browserTitle='Select input files';

%% Load user params
if nargin>=2
    % automatically get all input pairs (name, value) and store in local vairables
    for iArg=1:2:length(varargin)
        assignin_value(varargin{iArg},varargin{iArg+1});
    end
end

if ischar(inputsList) % convert char to cell array
    inputsList={inputsList}; % consider using "cellstr" instead of {}
end

%% Default programs param values
imageFormats=imformats;
imageFilesExtList=cat(2, imageFormats.ext);

videoFormats= VideoReader.getFileFormats();
videosFilesExtList={videoFormats.Extension};

% Fill file types and functions capable of quering for additional file properties.
% Currently image and video files are supported. Update thsi section for additional
% relevant files (say audio files etc...). note the ordering of both local variables
% should be respectively ordered.

% A cell array with elements specifying the relevant etention of file types
fileExt4FuncFileProps={imageFilesExtList, videosFilesExtList};
% The query functions appropriate for each file type described by file extentions above
hFuncFileProps={@imfinfo, @vFileInfo};

%% Prepare list of file names
if isempty(filesFilter) % default file types
    filesFilter=cat(2, imageFilesExtList, videosFilesExtList);
    % filesFilter={[]};
end

fileNamesList=filesListFromInput(inputsList, flagGUI, filesFilter, setInptsSource,...
    browserTitle);

% remove folders (if any) form the files list
isFolder=cellfun( @isdir, fileNamesList);
fileNamesList=fileNamesList( ~isFolder );
nFiles=length(fileNamesList);

%% Get basic file data via "dir" function
FileProps=cellfun( @dir, fileNamesList, 'UniformOutput', false );

%% Get file type specific data
% Get files extentions, to query for file type
[~, ~, fileExt]=cellfun(@fileparts, fileNamesList, 'UniformOutput', false);

% Get additional avalible files properties (for file types supporting such a query)
for iRelFileType=1:numel(fileExt4FuncFileProps)
    %% Create a cell array of structures with all data avalible for the file type
    % Combine fileds from various types, leaving irrelevant fields empty

    isRelFileType=false( size(fileExt) ); % init itertion variable chosing relevant files
    nRelExt=numel( fileExt4FuncFileProps{iRelFileType} );
    for iExt=1:nRelExt
        % Find files relevant to aditonal properties query function
        isRelFileType=isRelFileType |...
            strcmpi( strcat('.', fileExt4FuncFileProps{iRelFileType}{iExt}), fileExt );
    end
     
    if any(isRelFileType) % if such files ecist, apply query
        % get relevant files properties
        FileAdditionalProps=cellfun( hFuncFileProps{iRelFileType},...
            fileNamesList(isRelFileType), 'UniformOutput', false );
        % analyze properties names
        fieldsList=fieldnames(FileAdditionalProps{1});
        nFileds=numel(fieldsList);
        iRelFile=0;
        for iFile=1:nFiles % go thorugh all files
            if isRelFileType(iFile)
                iRelFile=iRelFile+1;
            end

            for iField=1:nFileds % for each newly added property
                currField=fieldsList{iField}; % get filed data
                if isRelFileType(iFile) % place filed data for relevant file types
                    FileProps{iFile}.(currField)=FileAdditionalProps{iRelFile}.(currField);
                else
                    % if irrelevant file type 
                    if isfield(FileProps{iFile}, currField)
                        continue; % Leave intact, if filed initiated with previous data
                    else
                        FileProps{iFile}.(currField)=[]; % Put empty (no data) filed data
                    end
                end	% if isVideoFile(iFile)
            end	% for iField=1:nFileds
        end	% for iFile=1:nFiles    
    end % if any(isRelFileType)
end

% Combine all data together

% Convert cell array of structures into an array of structures
FilePropsStruct=cell2mat(FileProps); 
% Get the relevant field data of all files
propFieldsList=cat(1, {FilePropsStruct.(files2filePropsFolders)} );
if strcmpi(files2filePropsFolders, 'date')
    % Convert to appropriate date format, ignoring minutes and seconds of file creation
    % time stamp
    propFieldsList=cellstr(datestr( datenum(propFieldsList,...
        'dd-mmm-yyyy HH:MM:SS'), 'yyyy-mm-dd' ));
end
isNumVal=cellfun(@isnumeric, propFieldsList);
propFieldsList(isNumVal)=cellfun(@num2str, propFieldsList(isNumVal), 'UniformOutput', false);
%% Apply operation (copy/move) to all files
hWaitbar=waitbar(0, 'Copying files:', 'Name', 'NikolayS files2FoldersProp.');
hTic=tic;

% Generate folder names based on selected file property values 
filesPropsFolders=unique( propFieldsList ); 
nFolders=length(filesPropsFolders);
iFileCount=0;
for iFolder=1:nFolders
    % find files of current property, to be moved to a given folder
    isTargFile=strcmpi( propFieldsList, filesPropsFolders(iFolder) );
    iFiles=find(isTargFile);
    if isempty(iFiles)
        continue; % if no such target files exist- skip.
    end
    targetFiles=fileNamesList(isTargFile);
    
    % generate targt folders, under folder of first relevant file 
    [currPath, ~, ~]= fileparts( fileNamesList{ iFiles(1) } ); 
    % pad the filesPropsFolders with path of first relevant file
    filesPropsFolders{iFolder}=strcat(currPath, filesep, filesPropsFolders{iFolder} );
    if exist( filesPropsFolders{iFolder}, 'file') ~= 7
        mkdir( filesPropsFolders{iFolder} ); % generate folder if it does not exist
    end
    
    % Apply fileOp to all apropriate files placing it into appropriate folder
    cellfun(fileOp, targetFiles, repmat( filesPropsFolders(iFolder), size(targetFiles) ));
    
    % calculate and update the progress bar
    iFileCount=iFileCount+numel(targetFiles);
    waitbarTimeRemaining(hWaitbar, hTic, iFileCount/nFiles);
end	% for iFolder=1:nFolders
close(hWaitbar);
% % get all moved/copied files names and path 
% fileNamesList=filesListFromInput(filesPropsFolders, [], [], 'Files list');

%% Service function
function vFileInfoProps=vFileInfo(vFile)
% get properties of a video file
VideoObj = VideoReader( vFile );
vFileInfoProps=get( VideoObj );

Contact us