I'm trying to build my own version of MATLAB's dir
function. My current code (below) almost works but I am having trouble parsing a certain combination of inputs.
What I would like it to do is this:
- Don't list hidden folders.
- Have a Boolean parameter (default is false) to return only directory names and not files.
- Have an optional field for the path of the folder (default is current directory).
To be clearer, I would like to create the function dir2
which can handle these combinations:
dir2
This should list every not-hidden file or folder in the current directory
dir2('path_to_directory')
This should list every not-hidden file or folder in the specified directory
dir2('OnlyDirectories', true)
This should list only the not-hidden folders in the current directory
dir2('path_to_directory', 'OnlyDirectories', true)
This should list only the not-hidden folders in the specified directory
My current version is this:
function list = dir2(varargin) p = inputParser; addOptional(p, 'name', '.', @ischar); addParameter(p, 'OnlyDirectories', false, @islogical); parse(p, varargin{:}); list = dir(p.Results.name); if p.Results.OnlyDirectories dirFlags = [list.isdir]; list = list(dirFlags); % Keeping only directories end % Deleting hidden folders from the list list = list(arrayfun(@(x) ~strcmp(x.name(1),'.'), list)); end
This works fine for cases 1, 2 and 4 but it doesn't work for case 3. In this case it gives me the error:
Expected a string scalar or character vector for the parameter name, instead the input type was 'logical'.
I think I might be missing something trivial about MATLAB's input parsing but I can't figure out what.
Answers:
You're right that the parser appears to give some odd results, a related question might be this one.
One work-around, which works for your function in its current form, would be to add a check for if 2 inputs are given. If there are 2 inputs, assume it's your OnlyDirectories
flag and use the default name
value. The code would look like this and passes all 4 of your example use cases.
function list = dir2(varargin) p = inputParser; addOptional(p, 'name', '.', @ischar); addParameter(p, 'OnlyDirectories', false, @islogical); if numel(varargin) == 2 varargin = [{'.'}, varargin]; end parse(p, varargin{:}); list = dir(p.Results.name); if p.Results.OnlyDirectories dirFlags = [list.isdir]; list = list(dirFlags); end list = list(arrayfun(@(x) ~strcmp(x.name(1),'.'), list)); end
This is a bit hacky though, and has scope to give confusing error messages. It would be better to just have both inputs as name-value pairs
function list = dir2(varargin) p = inputParser; addParameter(p, 'name', '.', @ischar); addParameter(p, 'OnlyDirectories', false, @islogical); % ... other code end