MATLAB Answers

John
1

Can you use DIR to list files in subfolders ?

Asked by John
on 12 Mar 2012
Latest activity Commented on by Walter Roberson
on 14 Aug 2019
Hello,
Would somebody be able to advise me on how to use DIR to find the dates that each file was last modified with a .mat extension in all sub folders in current directory?
This code does not look in sub directories. Also how to you specify the .mat extension.
files = dir(datenum)
Many thanks

  0 Comments

Sign in to comment.

Tags

6 Answers

Answer by Walter Roberson
on 12 Mar 2012
 Accepted Answer

You cannot do that in a single dir() call.
You need one dir() call on the current folder, and you look at the isdir() field of the results to see which names correspond to folders:
dirinfo = dir();
dirinfo(~[dirinfo.isdir]) = []; %remove non-directories
Then do a step to remove the folder names "." and ".." so you do not infinite loop.
Then you loop over all those names and look inside each of the designated folders:
subdirinfo = cell(length(dirinfo));
for K = 1 : length(dirinfo)
thisdir = dirinfo(K).name;
subdirinfo{K} = dir(fullfile(thisdir, '*.mat'));
end
Now subdirinfo{K} is the structure of information about the .mat files in the directory dirinfo(K).name

  6 Comments

dirinfo is a structure array. Picking one field out of a structure array results in structure expansion. Putting [] around the structure expansion results in a vector of the values. So it is like
[dirinfo(1).isdir, dirinfo(2).isdir, dirinfo(3).isdir, ....]
The ~ is logical negation, so ~ of the expression is going to result in true for the places that are not directories. And then that is used as a logical index to select the entries in the structure to delete.
Hi Walter,
I'm kinda understanding what you're saying. But please clarify if the statement means the following in words - "Assign NULL to the elements of the 'dirinfo' structure array which have '0' or FALSE in the isdir field." --Vidya
Only if you understand that assigning NULL means to delete them.

Sign in to comment.


Answer by Jan
on 3 May 2017

In modern Matlab versions:
files = dir('D:\Data\**\*.mat')

  8 Comments

Hi Jan, Thank you. i want to put those files in the new folder, can you please help me with the coding? i am a newbby and have been tring for days with no luck.
Yes , Right it works in 2017a and onwards.
Koustubh Shirke it works in R2016b and onwards.

Sign in to comment.


Answer by Walter Roberson
on 13 Mar 2012

filetofind = 'data.mat';
dirinfo = dir();
dirinfo(~[dirinfo.isdir]) = []; %remove non-directories
tf = ismember( {dirinfo.name}, {'.', '..'});
dirinfo(tf) = []; %remove current and parent directory.
numsubdir = length(dirinfo);
lastmod = inf * ones(numsubdir,1);
for K = 1 : numsubdir
subdirinfo = dir(fullfile(dirinfo(K).name, filetofind));
if ~isempty(subdirinfo)
lastmod(K) = subdirinfo(1).datenum;
end
end
[sortedmod, sortorder] = sort(lastmod);
sordorder(~isfinite(sortedmod)) = []; %directories without data.mat
for K = 1 : length(sortorder)
thisdirnum = sortorder(K);
thisoutname = sprintf('file%d.xls', K);
%copy from the subdirectory in to a sequentially named .xls file
copy( fullfile( dirinfo(thisdirnum).name, filetofind ), thisoutname );
end

  15 Comments

Hi Walter,
The variables are vectors of different sizes. The first variable is n X 1 and the the second variable is m x 2. So this means I need two xlswrite() calls. Is this correct? - Do I need two lines for "thisdata =" and "fprint" also?
Thanks for your help
John
filetofind = 'data.mat';
dirinfo = dir();
dirinfo(~[dirinfo.isdir]) = []; %remove non-directories
tf = ismember( {dirinfo.name}, {'.', '..'});
dirinfo(tf) = []; %remove current and parent directory.
numsubdir = length(dirinfo);
lastmod = inf * ones(numsubdir,1);
for K = 1 : numsubdir
subdirinfo = dir(fullfile(dirinfo(K).name, filetofind));
if ~isempty(subdirinfo)
lastmod(K) = subdirinfo(1).datenum;
end
end
[sortedmod, sortorder] = sort(lastmod);
sordorder(~isfinite(sortedmod)) = []; %directories without data.mat
vartofind = 'ess_plant_energy_in_total_simu';
vartofind1 = 'sch_cycle';
for K = 1 : length(sortorder)
thisdirnum = sortorder(K);
thisdirname = dirinfo(thisdirnum).name;
thisoutname = sprintf('file%d.xls', K);
try
thisdata = load( fullfile(thisdirname,filetofind), vartofind);
thisdata1 = load( fullfile(thisdirname,filetofind), vartofind1);
xlswrite( thisoutname, thisdata.(vartofind) );
xlswrite( thisoutname, thisdata1.(vartofind1) );
catch
fprintf(2, 'File "%s/%s" does not have variable "%s\n", thisdirname, filetofind, vartofind);
fprintf(2, 'File "%s/%s" does not have variable "%s\n", thisdirname, filetofind, vartofind1);
end
end
You can combine the load() into a single statement:
thisdata = load( fullfile(thisdirname,filetofind), vartofind, vartofind1 );
xlswrite( thisoutname, thisdata.(vartofind) );
xlswrite( thisoutname, thisdata.(vartofind1) );
However, you need to either write to different file names or else use range specifications on the xlswrite() -- otherwise the data from the second xlswrite() will overwrite the first.
Thanks very much for your help. I got it working.
Regards
John

Sign in to comment.


Answer by Frederic Moisy on 12 Mar 2012

  1 Comment

Hello Frederic,
Would you mind helping me code this for my application. I've been trying for hours with no luck.
Thank you
John

Sign in to comment.


Answer by Matthias on 3 May 2017
Edited by Matthias on 3 May 2017

Although this does not answer the whole question it adresses the title (which is what I was looking for): to get a list of all(!) subfolders below a specified folder or drive one could use the dos command like this:
[s, r] = dos('dir X:\folder\ /s /b /A:D');
folders = regexpi(r, '\n', 'split')';
Using the /s option the dos dir command will go down all the way (no option to specifiy a max recursion depth here - beware of long execution times!), with attribute D (/A:D) only directories will be returned and finally the /b option gives us a nice plain list (as a very long string) that can be easily split for further use.
Edit:
[s, r] = dos('dir X:\folder\*.mat /s /b');
matFiles = regexpi(r, '\n', 'split')';
will obviously give you the list of all .mat files, the date of these can easily be obtained with another dir() call:
l = cellfun(@dir, matFiles);
changeTimes = [l.datenum]';

  4 Comments

Show 1 older comment
Can you please help me with coding to put those files into the new folder?
thank you.
What files? What new folder?
It doesn't look like your question has much to do with the question being answered here, so please start your own question. Give as many details as possible about what you're trying to do.

Sign in to comment.


Answer by Ba Mo
on 21 Apr 2019

as lots of users reported above, new versions of matlab support the following command dir('**/*.mat');
However, old versions of matlab don't support this
instead of writing a large code, inspect the structure field "isfield" and so on, you could just easily ask DOS (or the command prompt) to do it for you. the output from MS-DOS isn't formatted, so you need to split the one block string to separate lines
newline = char(10); %char(10) is the character for line-break, or "enter"
[~,all_mats] = system('dir /s /b *.mat'); %you can also simply write: !dir /s /b *.mat
all_mats = strsplit(all_mats,newline)';
all_mats(cellfun(@isempty,all_mats))=[]; %the last entry/line might be an empty cell. delete it.

  0 Comments

Sign in to comment.