2

I want to check if directories exist but work them in a cell-array. Matlab where the data is in the cell array in fullDirectories

home='/home/masi/';
directories={ 'Images/Raw/'; 'Images/Data/'; 'Images/Series/' };
fullDirectories = strcat(home, directories);

I can check one directory by exist('/home/masi/', 'dir');. Pseudocode

existCellArray(fullDirectories, 'dir-cell'); 

Matlab: 2016a
OS: Debian 8.5

Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697

2 Answers2

3

You can use cellfun:

I took example from here: How to apply cellfun (or arrayfun or structfun) with constant extra input arguments?

The example uses an anonymous function:

cellfun(@(x)exist(x, 'dir'), fullDirectories)
Community
  • 1
  • 1
Rotem
  • 30,366
  • 4
  • 32
  • 65
3

Here's one approach.

%%% in file existCellArray.m
function Out = existCellArray (FullDirs)
% EXISTCELLARRAY - takes a cell array of *full* directory strings and tests if
%   they exist.

  MissingDirs = {};
  for i = 1 : length(FullDirs)
    if exist(FullDirs{i}, 'dir') 
      continue
    else 
      MissingDirs{end+1} = FullDirs{i}; 
    end
  end

  if isempty(MissingDirs); % Success
    Out = true; 
    return; 
  else % Failure: Missing folders detected. Print diagnostic message
    fprintf('Folder %s is missing\n', MissingDirs{:})
    Out = false;
  end
end

%%% in your console session:
Home = '/home/tasos/Desktop';
Dirs = {'dir1/subdir1', 'dir2/subdir2', 'dir3/subdir3'};
FullDirs = fullfile(Home, Dirs); % this becomes a cell array!
existCellArray (FullDirs)

%%% console output:
Folder /home/tasos/Desktop/dir2/subdir2 is missing
Folder /home/tasos/Desktop/dir3/subdir3 is missing
ans = 0

Note that one shouldn't automatically have a dislike for loops; I feel that in this case it is preferable:

  • it is efficient
  • it is clear, readable, debuggable code (whereas the output from cellfun is cryptic and hard to put to further use)
  • it allows for custom handling
  • a good for loop can actually be faster:

    >> tic; for i = 1 : 1000; cellfun(@(x)exist(x, 'dir'), FullDirs); end; toc
    Elapsed time is 3.66625 seconds.
    >> tic; for i = 1 : 1000; existCellArray(FullDirs); end; toc;
    Elapsed time is 0.405849 seconds.
    
Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57
  • 1
    `cellfun` is no better than a loop, it's just a fancier loop, not faster. Just like `arrayfun`. Also as long as you are not dealing with nested loops, `for` loops are usually _very_ quick. – EBH Sep 03 '16 at 22:14
  • 1
    Yes, exactly, there's sometimes this knee jerk reaction that "vectorised is always faster" (which I get the feel is the case above), but this is not necessarily true; and in this particular case it turns out to be 10 times slower! :) – Tasos Papastylianou Sep 03 '16 at 22:18
  • 2
    Well the true is vectorised _is_ alway faster, BUT `cellfun` and it's 'relatives' are simply not vectorised! – EBH Sep 03 '16 at 22:19
  • 1
    I will admit I don't know underlying implementation details for either. Though I do think before all this JIT compilation business kicked in properly, in the old days it *did* seem you could speed things up using `arrayfun` instead of a loop. That advantage may well have disappeared now though ... – Tasos Papastylianou Sep 03 '16 at 22:21
  • 1
    @Masi ah yes, sorry, I wrote this in octave where`"` and `i{}` is valid syntax, but it seems matlab didn't like it. I fixed the bug above. – Tasos Papastylianou Sep 04 '16 at 08:18
  • Yes, it means that `i` expanded to more than just one argument. The syntax `i{:}` means "express all elements of cell array `i` as a comma separated list", which you can pass as a list of arguments into functions, or even use to create arrays, e.g. `[i{:}]`. In my for loop, `i` should always be a cell containing a single element taken from the `FullDirs` cell array. I used `{:}` because I expect it to only expand to a single argument anyway. Are you using it in a different way? If you debug and print the value of `i` on the terminal before line 8, what does it say `i` is? – Tasos Papastylianou Sep 04 '16 at 12:43
  • Did you by any chance build your cell array as a "vertical" array? i.e. `Dirs = {'dir1/subdir1'; 'dir2/subdir2'; 'dir3/subdir3'};` instead of `Dirs = {'dir1/subdir1', 'dir2/subdir2', 'dir3/subdir3'};` ? Compare the following: `a = [1,2,3,4,5;6,7,8,9,10]; for i = a; disp(sum(i)); end;` and `a = a'; for i = a; disp(sum(i)); end;` – Tasos Papastylianou Sep 04 '16 at 12:51
  • 1
    more relevant example. `a = {'ab','cd','ef';'gh','ij','kl'}`. compare `for i = a; [i{:}], end` vs `for i = a'; [i{:}], end` – Tasos Papastylianou Sep 04 '16 at 13:00
  • 1
    Hi @Masi , no, I'm guessing the problem is you're doing d1;d2;d3 instead of d1,d2,d3 (i.e. semicolons instead of commas). If you'd like I can rewrite my example to make it easier to follow – Tasos Papastylianou Sep 05 '16 at 08:47
  • 1
    I've edited the answer to make the code simpler and easier to follow. It should now work whether you define your FullDirs as a vertical or horizontal array. – Tasos Papastylianou Sep 05 '16 at 08:56