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

86

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

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

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

Теги:
directory
file
recursion
file-io

8 ответов

119
Лучший ответ

Обновление: Учитывая, что этот пост довольно старый, и я модифицировал эту утилиту для моего собственного использования в течение этого времени, я думал, что должен опубликовать новую версию. Мой новейший код можно найти на Файловый обмен 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');
  • 0
    Как заставить его возвращать полный путь, а не только имена файлов?
  • 3
    +1 - отличное решение. Я не знаю, если это необходимо, но если вы вставите строку: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); в ваше решение между первым определением fileList и определением subDirs, он вернет полный путь и имя файла для каждого файла.
Показать ещё 12 комментариев
23

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

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

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: []
  • 0
    Можете ли вы заставить его искать рекурсивно, включая файлы в подкаталогах, но исключая сам каталог?
  • 0
    Нет, не в моей голове, нет (у меня больше нет регулярного доступа к Matlab), но это может вам помочь: mathworks.com/matlabcentral/fileexchange/…
Показать ещё 4 комментария
13

Я использовал код, упомянутый в этот отличный ответ, и расширил его, чтобы поддерживать 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)));

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

  • 0
    +1, это очень компактно, но не ищет рекурсивно.
  • 0
    @Runner: Да, если вы используете циклы for и while ... но я ленив, чтобы реализовать это прямо сейчас.
Показать ещё 1 комментарий
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.

Positive:

  • Очень быстро (в моем случае для базы данных из 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 массива ячеек. Я не знаю, как это сделать.

  • 0
    По соображениям производительности я не хочу genpath , он, по сути, ищет дважды.
  • 2
    Недостатком использования GENPATH является то, что он будет включать только те подкаталоги, которые разрешены в пути MATLAB. Например, если у вас есть каталоги с именем private , они не будут включены.
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  

Ещё вопросы

Сообщество Overcoder
Наверх
Меню