list.files(...)
My preferred programing language is R. But, for many purposes, I find myself in need of a Graphical User Interface (GUI). Thus, I experienced a forceful transition to Matlab. Let’s be honest, Matlab can do powerful things, and it’s a great language to attempt to dominate (note to self: learn Python!1). Still, I find myself over and over thinking in R
mode. Something along the lines of:
Gimme all the files in folder with xyz…
Can be easily accomplished in R
with list.files()
This command can handle many many options, with pattern
being among my favorite. More importantly, this command returns a useful character
vector. No extra dots, no list of lists, no array. Just, useful. On the other hand, Matlab has dir
and ls
both of which are not satisfactory.
dir
.
..
something.m
something_else.m LookHere.m
Yes… Matlab’s version can also handle some form of regular expression matching. But, mind the dots and the structure! Matlab’s dir
has a ton of things on it.
>> q = dir
=
q
20×1 struct array with fields:
name
folderdate
bytesisdir
datenum
Matlab ls
function is also full of deadly traps.
= ls
qq
=
qq
20×28 char array
'. '
'.. '
'many_things_here.ext '
The solution
I found myself fighting for a character vector or array (nx1
) that I could feed into a function/loop/whatever.
Thus, after many many many times fighting against classes, with functions that expect char
instead of string
, or cell
, or whatever
, I decided to create something that resembles (at least partially) the functionality I was looking for. It’s not perfect. Please enlighten me with a better approach. For now, I will be using list_files.m
. Wanna use it? Be my guest, see below:
Show Matlab Code
% The idea of this function is to have something that works to list files
% Matlab has too many weird things with dir/patterns/etc...
% It could be slow if calling in a BIG dir and then subsetting
% Otherwise it should work pretty fast
function filenames = list_files(varargin)
% Open input parser
= inputParser();
p
% Add possible values
, 'Interactive', true, @islogical)
addOptional(p, 'Dirname', '0', @ischar)
addOptional(p, 'Pattern', {'.'}, @iscell)
addOptional(p, 'FullPath', false, @islogical)
addOptional(p
% parse
, varargin{:});
parse(p
% retrieve things from parser
= p.Results.Interactive;
Interactive = p.Results.Dirname;
Dirname = p.Results.Pattern;
Pattern = p.Results.FullPath;
FullPath
%% Dirname goes first
% If we didn't provide a Dirname, both defaults will hold
% If we provided a Dirname, we will read from there
if (Interactive && string(Dirname) == '0')
= uigetdir();
dirname
else
= Dirname;
dirname
end
if ~isdir(dirname)
error('Dirname not valid, check dirname provided is character and exists.')
end
% actually call dir
=dir(dirname);
d% Remove the dots matlab puts to things
=d(~ismember({d.name},{'.','..'}));
d
% Get filenames
% Output as an mx1 cell
= {d.name}';
filenames
%% Subset by pattern
= string(Pattern) == '.';
default_pattern
if (~default_pattern) % non default case
% join cell patterns separated by the 'or' regular expression
= strjoin(Pattern, '|');
query_expression
% Subset the patterns
= filenames(~cellfun(@isempty,regexp(filenames, query_expression)));
filenames end
% By default we return just the name
% If you want the full path, call it!
% it currently works only for 1 folder
% Recursive = TRUE will be super nice!
if FullPath
= fullfile(unique({d.folder}), filenames);
filenames end
end
Footnotes
Reuse
Citation
@online{andina2018,
author = {Andina, Matias},
title = {Matlab List\_files},
date = {2018-04-24},
url = {https://matiasandina.com/posts/2018-04-24-matlab-list-files},
langid = {en}
}