Problems converting folders in a directory from cell array into individual nested structures.

2 views (last 30 days)
I have written a code to first read all folders in a directory and convert them into separated nested structures but the code I found in Community page only gives a cell array. Diagram 3 is the end result I am trying to get. Within each folder (e.g TE_View_02_24mm_10deg_f11_1.1deg) contains the structure 'KeyData'.
TopLevelFolder = "C:\Users";
files = dir(TopLevelFolder); % Get a list of all files and folders in this folder.
dirFlags = [files.isdir]; % Get a logical vector that tells which is a directory.
subFolders = files(dirFlags); % A structure with extra info.
% Get only the folder names into a cell array.
subFolderNames = {subFolders(3:end).name}; % Start at 3 to skip . and ..
Items = {'Folder_Names'};
Folders = cell2struct(subFolderNames, Items, 1);
SampleData1 = zeros(256,512);
SampleData2 = zeros(1,512);
KeyData = struct('x',SampleData1,'y',SampleData1,'U',SampleData1, 'V', SampleData1,'Vorticity',SampleData2,'Circulation',SampleData2);
for i = 1:length(subFolderNames)
Given_Folders(i).Names = struct(Folders(i).Folder_Names,KeyData);
end
Diagram 1: Folders' name
Diagram 2: Error statement
Diagram 3: Desired outcome
  1 Comment
Stephen23
Stephen23 on 6 Oct 2022
Edited: Stephen23 on 6 Oct 2022
Your code is very convoluted. Instead of simply using DIR's output (which would give you the folder names without any extra effort), you use indexing to create another structure array which you convert to a cell array using a comma-separated list which you then convert back to a structure array with only one field which you then refer to when creating a scalar structure which you then nest inside another new structure array.
This is waaaaaay too complex for such a simple task. So many structure arrays, all containing the same information: rather than duplicating the file information in lots of variables (i.e. FILES, SUBFOLDERS, FOLDERS, GIVENFOLDERS) why not just use the same structure? The code is a very convoluted way to simply keep the same information.
Note that this is a buggy attemp to remove the dot directory names:
subFolderNames = {subFolders(3:end).name}; % !!! BUGGY !!!
The robust approach is to use ISMEMBER, SETDIFF, or similar. For more information, see:
As Walter Roberson wrote in that last link: "In short: if your code assumes that '.' and '..' are the first two entries in a directory, your code has a bug (even in MS Windows). If your code assumes that directory entries are returned in any sorted order, your code has a bug (in all OS.)"

Sign in to comment.

Accepted Answer

Jan
Jan on 6 Oct 2022
The field names cannot contain a dot. Remove the dots:
...
for i = 1:length(subFolderNames)
name = strrep(Folders(i).Folder_Names, '.', ''); % Or replace by _
Given_Folders(i).Names = struct(name, KeyData);
end
  2 Comments
Kai Jun Chern
Kai Jun Chern on 6 Oct 2022
Awesome, thanks a lot! That worked well.
This led me to the following figures which is close to what I wanted.
Is it possible to have all the files' name directly shown under 'Names' instead of 15 '1x1 struct'? I am not so sure how to write it as such in the 'for' loop. Appreciate your input
Stephen23
Stephen23 on 6 Oct 2022
Edited: Stephen23 on 6 Oct 2022
"Is it possible to have all the files' name directly shown under 'Names' instead of 15 '1x1 struct'? I am not so sure how to write it as such in the 'for' loop. Appreciate your input"
Nope, not if you insist on using lots of nested scalar structures.
But nested structures are not so convenient, here is a simpler and much more robust approach:
% just for testing here on this forum
mkdir hello
mkdir world
%
P = '.'; %"C:\Users";
S = dir(fullfile(P,'*'));
S(~[S.isdir]) = [];
S(ismember({S.name},{'.','..'})) = [] % robust
S = 2×1 struct array with fields:
name folder date bytes isdir datenum
SampleData1 = zeros(256,512);
SampleData2 = zeros(1,512);
%
[S.x] = deal(SampleData1);
[S.y] = deal(SampleData1);
[S.U] = deal(SampleData1);
[S.V] = deal(SampleData1);
[S.Vorticity] = deal(SampleData2);
[S.Circulation] = deal(SampleData2)
S = 2×1 struct array with fields:
name folder date bytes isdir datenum x y U V Vorticity Circulation
Also note that preallocation of structure fields is only useful if they will be indexed into later. If they are replaced entirely (i.e. reallocated to another array) then storing SAMPLEDATA1/2 serves no purpose, just slows down the code.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!