Как получить все файлы в определенном каталоге в MATLAB?

102

Мне нужно собрать все эти файлы D:\dicи перебрать их для дальнейшей обработки индивидуально.

Поддерживает ли MATLAB такие операции?

Это можно сделать в других скриптах, таких как PHP, Python ...

Gtker
источник

Ответы:

130

Обновление: учитывая, что этот пост довольно старый, и я много модифицировал эту утилиту для собственного использования в течение того времени, я подумал, что должен опубликовать новую версию. Мой новейший код можно найти на The MathWorks Файл обмена : dirPlus.m. Вы также можете получить исходный код с GitHub .

Сделал ряд улучшений. Теперь он дает вам возможность добавить полный путь или вернуть только имя файла ( взято из Doresoom и Oz Radiano ) и применить шаблон регулярного выражения к именам файлов (полученный из Peter D ). Кроме того, я добавил возможность применять функцию проверки к каждому файлу, что позволяет вам выбирать их на основе критериев, отличных от их имен (например, размер файла, содержимое, дата создания и т. Д.).


ПРИМЕЧАНИЕ. В более новых версиях MATLAB (R2016b и позже) dirфункция имеет возможности рекурсивного поиска! Таким образом, вы можете сделать это, чтобы получить список всех *.mфайлов во всех подпапках текущей папки:

dirData = dir('**/*.m');

Старый код: (для потомков)

Вот функция, которая рекурсивно выполняет поиск во всех подкаталогах данного каталога, собирая список всех имен файлов, которые она находит:

function fileList = getAllFiles(dirName)

  dirData = dir(dirName);      %# Get the data for the current directory
  dirIndex = [dirData.isdir];  %# Find the index for directories
  fileList = {dirData(~dirIndex).name}';  %'# Get a list of the files
  if ~isempty(fileList)
    fileList = cellfun(@(x) fullfile(dirName,x),...  %# Prepend path to files
                       fileList,'UniformOutput',false);
  end
  subDirs = {dirData(dirIndex).name};  %# Get a list of the subdirectories
  validIndex = ~ismember(subDirs,{'.','..'});  %# Find index of subdirectories
                                               %#   that are not '.' or '..'
  for iDir = find(validIndex)                  %# Loop over valid subdirectories
    nextDir = fullfile(dirName,subDirs{iDir});    %# Get the subdirectory path
    fileList = [fileList; getAllFiles(nextDir)];  %# Recursively call getAllFiles
  end

end

После сохранения вышеупомянутой функции где-нибудь на вашем пути к MATLAB вы можете вызвать ее следующим образом:

fileList = getAllFiles('D:\dic');
Гновице
источник
3
+1 - Отличное решение. Не знаю, нужно ли это, но если вставить строку: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); в ваше решение между первым определением fileList и определением subDirs, он вернет полный путь и имя файла для каждого файла.
Doresoom
2
@Doresoom: Хорошее предложение, хотя вместо этого я использовал FULLFILE, поскольку он обрабатывает выбор разделителя файлов за вас (который отличается в UNIX и Windows). Кроме того, вы можете просто использовать fileList = strcat(dirName,filesep,fileList);вместо CELLFUN, хотя в результате вы можете получить лишние ненужные разделители файлов, о которых FULLFILE позаботится и за вас.
gnovice
2
@gnovice, @Doreseoom - согласно mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , порядок, в котором возвращается 'dir', зависит от ОС. Я не уверен, что произойдет, если, например, вы установите для переменной DOS DIRCMD значение, изменяющее порядок. Octave справляется с этим нормально (... и ... все еще первые), но у меня нет MATLAB для тестирования.
mtrw
2
@gnovice: это выходит за рамки вопроса OP, но я счел полезным встроить регулярные выражения в функцию. if ~isempty(fileList) fileList = cellfun(@(x) fullfile(dirName,x),... %# Prepend path to files fileList,'UniformOutput',false); matchstart = regexp(fileList, pattern); fileList = fileList(~cellfun(@isempty, matchstart)); end и измените подпись функции на getAllFiles(dirName, pattern)(также во второй и последней строке)
Peter D
1
Отличный ответ, спасибо! Я разработал код для поддержки двух дополнительных параметров - stackoverflow.com/a/26449095/69555
Oz Radiano,
25

Вы ищете реж вернуть содержимое каталога.

Чтобы просмотреть результаты, вы можете просто сделать следующее:

dirlist = dir('.');
for i = 1:length(dirlist)
    dirlist(i)
end

Это должно дать вам вывод в следующем формате, например:

name: 'my_file'
date: '01-Jan-2010 12:00:00'
bytes: 56
isdir: 0
datenum: []
Джеймс Б.
источник
Можете ли вы заставить его выполнять рекурсивный поиск, включая файлы в подкаталогах, но исключая сам каталог?
Gtker
Не из головы, нет (у меня больше нет постоянного доступа к Matlab), но это может вам помочь: mathworks.com/matlabcentral/fileexchange/…
Джеймс Б.
2
Как исключить .и ..?
Gtker
5
@Runner: исключить. и .. удалите первые две записи в выводе dir. Или, если вы ищете конкретный тип файла, запустите dir('*.ext'), что автоматически исключает каталоги (если они, конечно, не заканчиваются на .ext)
Джонас
14

Я использовал код, упомянутый в этом замечательном ответе, и расширил его для поддержки 2 дополнительных параметров, которые мне нужны в моем случае. Параметры - это расширения файлов для фильтрации и флаг, указывающий, следует ли объединять полный путь с именем файла или нет.

Я надеюсь, что это достаточно ясно и кому-то будет полезно.

function fileList = getAllFiles(dirName, fileExtension, appendFullPath)

  dirData = dir([dirName '/' fileExtension]);      %# Get the data for the current directory
  dirWithSubFolders = dir(dirName);
  dirIndex = [dirWithSubFolders.isdir];  %# Find the index for directories
  fileList = {dirData.name}';  %'# Get a list of the files
  if ~isempty(fileList)
    if appendFullPath
      fileList = cellfun(@(x) fullfile(dirName,x),...  %# Prepend path to files
                       fileList,'UniformOutput',false);
    end
  end
  subDirs = {dirWithSubFolders(dirIndex).name};  %# Get a list of the subdirectories
  validIndex = ~ismember(subDirs,{'.','..'});  %# Find index of subdirectories
                                               %#   that are not '.' or '..'
  for iDir = find(validIndex)                  %# Loop over valid subdirectories
    nextDir = fullfile(dirName,subDirs{iDir});    %# Get the subdirectory path
    fileList = [fileList; getAllFiles(nextDir, fileExtension, appendFullPath)];  %# Recursively call getAllFiles
  end

end

Пример запуска кода:

fileList = getAllFiles(dirName, '*.xml', 0); %#0 is false obviously
Оз Радиано
источник
8

Вы можете использовать regexp или strcmp для исключения .и .. или вы можете использовать isdirполе, если вам нужны только файлы в каталоге, а не папки.

list=dir(pwd);  %get info of files/folders in current directory
isfile=~[list.isdir]; %determine index of files vs folders
filenames={list(isfile).name}; %create cell array of file names

или объедините две последние строчки:

filenames={list(~[list.isdir]).name};

Для списка папок в каталоге исключая. и ..

dirnames={list([list.isdir]).name};
dirnames=dirnames(~(strcmp('.',dirnames)|strcmp('..',dirnames)));

С этого момента вы должны иметь возможность вставлять код во вложенный цикл for и продолжать поиск в каждой подпапке, пока ваши dirnames не вернут пустую ячейку для каждого подкаталога.

Doresoom
источник
@Runner: Да, если вы используете некоторые циклы for и while ... но мне лень реализовывать это прямо сейчас.
Doresoom
+1 даже при том, что он не совсем отвечает на вопрос, он дает способ быстро отсеивать каталоги.
jhfrontz 08
7

Этот ответ не дает прямого ответа на вопрос, но может быть хорошим нестандартным решением.

Я поддержал решение gnovice, но хочу предложить другое решение: используйте системно-зависимую команду вашей операционной системы:

tic
asdfList = getAllFiles('../TIMIT_FULL/train');
toc
% Elapsed time is 19.066170 seconds.

tic
[status,cmdout] = system('find ../TIMIT_FULL/train/ -iname "*.wav"');
C = strsplit(strtrim(cmdout));
toc
% Elapsed time is 0.603163 seconds.

Положительный:

  • Очень быстро (в моем случае для базы данных из 18000 файлов на linux).
  • Вы можете использовать хорошо проверенные решения.
  • Вам не нужно изучать или изобретать новый синтаксис для выбора *.wavфайлов, т.е.

Отрицательный:

  • Вы не независимы от системы.
  • Вы полагаетесь на одну строку, которую может быть трудно разобрать.
Лукас
источник
3

Я не знаю однофункционального метода для этого, но вы можете использовать только genpathдля рекурсии списка подкаталогов . Этот список возвращается в виде строки каталогов, разделенных точкой с запятой, поэтому вам придется разделить его с помощью strread, т.е.

dirlist = strread(genpath('/path/of/directory'),'%s','delimiter',';')

Если вы не хотите включать данный каталог, удалите первую запись dirlist, т. Е. dirlist(1)=[];Поскольку это всегда первая запись.

Затем получите список файлов в каждом каталоге с помощью цикла dir.

filenamelist=[];
for d=1:length(dirlist)
    % keep only filenames
    filelist=dir(dirlist{d});
    filelist={filelist.name};

    % remove '.' and '..' entries
    filelist([strmatch('.',filelist,'exact');strmatch('..',filelist,'exact'))=[];
    % or to ignore all hidden files, use filelist(strmatch('.',filelist))=[];

    % prepend directory name to each filename entry, separated by filesep*
    for f=1:length(filelist)
        filelist{f}=[dirlist{d} filesep filelist{f}];
    end

    filenamelist=[filenamelist filelist];
end

filesep возвращает разделитель каталогов для платформы, на которой работает MATLAB.

Это дает вам список имен файлов с полными путями в массиве ячеек filenamelist . Я знаю, что не самое лучшее решение.

JS Ng
источник
По соображениям производительности я не хочу genpathэтого, по сути, он выполняет поиск дважды.
Gtker
2
Одним из недостатков использования GENPATH является то, что он будет включать только подкаталоги, которые разрешены на пути MATLAB. Например, если у вас есть названные каталоги private, они не будут включены.
gnovice
1

Это удобная функция для получения имен файлов в указанном формате (обычно .mat) в корневой папке!

    function filenames = getFilenames(rootDir, format)
        % Get filenames with specified `format` in given `foler` 
        %
        % Parameters
        % ----------
        % - rootDir: char vector
        %   Target folder
        % - format: char vector = 'mat'
        %   File foramt

        % default values
        if ~exist('format', 'var')
            format = 'mat';
        end

        format = ['*.', format];
        filenames = dir(fullfile(rootDir, format));
        filenames = arrayfun(...
            @(x) fullfile(x.folder, x.name), ...
            filenames, ...
            'UniformOutput', false ...
        );
    end

В вашем случае вы можете использовать следующий фрагмент :)

filenames = getFilenames('D:/dic/**');
for i = 1:numel(filenames)
    filename = filenames{i};
    % do your job!
end
Яс
источник
0

С небольшими изменениями, но почти схожим подходом для получения полного пути к каждой подпапке

dataFolderPath = 'UCR_TS_Archive_2015/';

dirData = dir(dataFolderPath);      %# Get the data for the current directory
dirIndex = [dirData.isdir];  %# Find the index for directories
fileList = {dirData(~dirIndex).name}';  %'# Get a list of the files
if ~isempty(fileList)
    fileList = cellfun(@(x) fullfile(dataFolderPath,x),...  %# Prepend path to files
        fileList,'UniformOutput',false);
end
subDirs = {dirData(dirIndex).name};  %# Get a list of the subdirectories
validIndex = ~ismember(subDirs,{'.','..'});  %# Find index of subdirectories
%#   that are not '.' or '..'
for iDir = find(validIndex)                  %# Loop over valid subdirectories
    nextDir = fullfile(dataFolderPath,subDirs{iDir});    %# Get the subdirectory path
    getAllFiles = dir(nextDir);
    for k = 1:1:size(getAllFiles,1)
        validFileIndex = ~ismember(getAllFiles(k,1).name,{'.','..'});
        if(validFileIndex)
            filePathComplete = fullfile(nextDir,getAllFiles(k,1).name);
            fprintf('The Complete File Path: %s\n', filePathComplete);
        end
    end
end  
Spandan
источник