Як отримати всі файли в певному каталозі в MATLAB?


102

Мені потрібно взяти всі ці файли D:\dicі перетворити цикл на них для подальшої обробки окремо.

Чи підтримує MATLAB такий вид операцій?

Це можна зробити в інших сценаріях, таких як PHP, Python ...

Відповіді:


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: Це поза питанням ОП, але я вважаю корисним вбудовувати регулярні вирази у функцію. 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)(також у другому до останнього рядка)
Петро Д

1
Чудова відповідь, дякую! Я розробив код для підтримки 2 додаткових параметрів - stackoverflow.com/a/26449095/69555
Oz Radiano

25

Ви шукаєте 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: []

Чи можете ви змусити його здійснювати пошук рекурсивно, включаючи файли у підкаталогах, але виключаючи сам каталог?
Gtker

Ні, не зверху голови, ні (я більше не маю регулярного доступу до Matlab), але це може вам допомогти: mathworks.com/matlabcentral/fileexchange/…
Джеймс Б,

2
Як виключити .і ..?
Gtker

5
@Runner: виключити. і .., видаліть перші два записи у висновку dir. Або, якщо ви шукаєте конкретний тип файлу, запустіть dir('*.ext'), що автоматично виключає каталоги (якщо, звичайно, вони не закінчуються .ext)
Jonas

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

Ви можете використовувати регулярний вираз або 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)));

З цього моменту ви зможете кинути код у вкладений цикл і продовжити пошук кожної підпапки, поки ваші dirname не повернуть порожню комірку для кожного підкаталогу.


@Runner: Це робиться, якщо ви використовуєте певні для циклів і поки ... але я лінусь реалізувати це прямо зараз.
Doresoom

+1, навіть якщо він точно не відповідає на запитання, але дає спосіб швидко вилучити каталоги.
jhfrontz

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.

Це дає вам список імен файлів із повними шляхами в назви файлів масиву комірок . Я не найновіше рішення, я знаю.


З причини продуктивності я не хочу 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  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.