Wie bekomme ich alle Dateien in einem bestimmten Verzeichnis in MATLAB?


102

Ich muss all diese Dateien untergehen D:\dicund sie durchlaufen, um sie einzeln weiter zu verarbeiten.

Unterstützt MATLAB diese Art von Operationen?

Es kann in anderen Skripten wie PHP, Python ...

Antworten:


130

Update: Da dieser Beitrag ziemlich alt ist und ich dieses Dienstprogramm in dieser Zeit stark für meinen eigenen Gebrauch geändert habe, dachte ich, ich sollte eine neue Version veröffentlichen. Mein neuester Code ist in The MathWorks File Exchange zu finden : dirPlus.m. Sie können die Quelle auch von GitHub erhalten .

Ich habe einige Verbesserungen vorgenommen. Sie haben jetzt die Möglichkeit, den vollständigen Pfad voranzustellen oder nur den Dateinamen (von Doresoom und Oz Radiano übernommen ) zurückzugeben und den Dateinamen (von Peter D übernommen ) ein Muster mit regulären Ausdrücken zuzuweisen . Darüber hinaus habe ich die Möglichkeit hinzugefügt, auf jede Datei eine Validierungsfunktion anzuwenden, mit der Sie sie anhand anderer Kriterien als nur ihrer Namen (z. B. Dateigröße, Inhalt, Erstellungsdatum usw.) auswählen können.


HINWEIS: In neueren Versionen von MATLAB (R2016b und höher) verfügt die dirFunktion über rekursive Suchfunktionen! So können Sie eine Liste aller *.mDateien in allen Unterordnern des aktuellen Ordners abrufen:

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

Alter Code: (für die Nachwelt)

Hier ist eine Funktion, die rekursiv alle Unterverzeichnisse eines bestimmten Verzeichnisses durchsucht und eine Liste aller gefundenen Dateinamen sammelt:

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

Nachdem Sie die obige Funktion irgendwo in Ihrem MATLAB-Pfad gespeichert haben, können Sie sie folgendermaßen aufrufen:

fileList = getAllFiles('D:\dic');

3
+1 - Großartige Lösung. Ich weiß nicht, ob es notwendig ist, aber wenn Sie die Zeile einfügen: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); In Ihrer Lösung zwischen der ersten fileList-Definition und der subDirs-Definition werden der vollständige Pfad und der Dateiname für jede Datei zurückgegeben.
Doresoom

2
@Doresoom: Guter Vorschlag, obwohl ich stattdessen FULLFILE verwendet habe, da es die Auswahl des Dateitrennzeichens für Sie übernimmt (was unter UNIX und Windows unterschiedlich ist). Sie können auch einfach fileList = strcat(dirName,filesep,fileList);CELLFUN verwenden, obwohl Sie auf diese Weise zusätzliche unnötige Dateitrennzeichen erhalten können, die FULLFILE auch für Sie erledigt.
Gnovice

2
@gnovice, @Doreseoom - Laut mathworks.com/access/helpdesk/help/techdoc/ref/dir.html ist die Reihenfolge, in der 'dir' zurückgegeben wird, vom Betriebssystem abhängig. Ich bin nicht sicher, was passiert, wenn Sie beispielsweise die Variable DOS DIRCMD auf etwas setzen, das die Reihenfolge ändert. Octave handhabt es in Ordnung (. Und .. sind immer noch die ersten), aber ich habe kein MATLAB zum Testen.
mtrw

2
@gnovice: Dies steht außer Frage des OP, aber ich fand es nützlich, reguläre Ausdrücke in die Funktion einzubauen. 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 und ändern Sie die Funktionssignatur in getAllFiles(dirName, pattern)(auch in der 2. bis letzten Zeile)
Peter D

1
Tolle Antwort, danke! Ich habe den Code ausgearbeitet, um 2 zusätzliche Parameter zu unterstützen - stackoverflow.com/a/26449095/69555
Oz Radiano

25

Sie suchen nach dir , um den Verzeichnisinhalt zurückzugeben.

Um die Ergebnisse zu durchlaufen, können Sie einfach Folgendes tun:

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

Dies sollte Ihnen eine Ausgabe im folgenden Format geben, z.

name: 'my_file'
date: '01-Jan-2010 12:00:00'
bytes: 56
isdir: 0
datenum: []

Können Sie es rekursiv suchen lassen, einschließlich Dateien in Unterverzeichnissen, aber ohne Verzeichnis selbst?
Gtker

Nicht aus dem Kopf, nein (ich habe keinen regulären Zugang mehr zu Matlab), aber das kann Ihnen helfen: mathworks.com/matlabcentral/fileexchange/…
James B.

2
Wie ausschließen .und ..?
Gtker

5
@ Runner: ausschließen. und .. entfernen Sie die ersten beiden Einträge in der Ausgabe von dir. Oder, falls Sie nach einem bestimmten Dateityp suchen, führen Sie aus dir('*.ext'), wodurch Verzeichnisse automatisch ausgeschlossen werden (es sei denn, sie enden natürlich mit .ext)
Jonas

14

Ich habe den in dieser großartigen Antwort erwähnten Code verwendet und ihn erweitert, um 2 zusätzliche Parameter zu unterstützen, die ich in meinem Fall benötigte. Die Parameter sind Dateierweiterungen, nach denen gefiltert werden soll, und ein Flag, das angibt, ob der vollständige Pfad zum Namen der Datei verkettet werden soll oder nicht.

Ich hoffe, es ist klar genug und jemand wird es nützlich finden.

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

Beispiel für die Ausführung des Codes:

fileList = getAllFiles(dirName, '*.xml', 0); %#0 is false obviously

8

Sie können Regexp oder Strcmp verwenden, um zu entfernen, .und .. Sie können das isdirFeld auch verwenden, wenn Sie nur Dateien im Verzeichnis und keine Ordner möchten.

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

oder kombinieren Sie die letzten beiden Zeilen:

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

Für eine Liste der Ordner im Verzeichnis ausgenommen. und ..

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

Ab diesem Punkt sollten Sie in der Lage sein, den Code in eine verschachtelte for-Schleife zu werfen und jeden Unterordner weiter zu durchsuchen, bis Ihre Verzeichnisnamen eine leere Zelle für jedes Unterverzeichnis zurückgeben.


@ Runner: Es funktioniert, wenn Sie einige for- und while-Schleifen verwenden ... aber ich bin zu faul, um das jetzt zu implementieren.
Doresoom

+1, obwohl es die Frage nicht genau beantwortet, bietet es eine Möglichkeit, die Verzeichnisse schnell auszusortieren.
Jhfrontz

7

Diese Antwort beantwortet die Frage nicht direkt, kann aber eine gute Lösung sein.

Ich habe die Lösung von gnovice verbessert, möchte aber eine andere Lösung anbieten: Verwenden Sie den systemabhängigen Befehl Ihres Betriebssystems:

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.

Positiv:

  • Sehr schnell (in meinem Fall für eine Datenbank mit 18000 Dateien unter Linux).
  • Sie können gut getestete Lösungen verwenden.
  • Sie müssen keine neue Syntax lernen oder neu erfinden, um dh *.wavDateien auszuwählen .

Negativ:

  • Sie sind nicht systemunabhängig.
  • Sie verlassen sich auf eine einzelne Zeichenfolge, die möglicherweise schwer zu analysieren ist.

3

Ich kenne hierfür keine Einzelfunktionsmethode, aber Sie können genpathnur eine Liste von Unterverzeichnissen verwenden . Diese Liste wird als durch Semikolons getrennte Zeichenfolge von Verzeichnissen zurückgegeben, sodass Sie sie mit strread trennen müssen, d. H.

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

Wenn Sie das angegebene Verzeichnis nicht einschließen möchten, entfernen Sie den ersten Eintrag von dirlist, dh, dirlist(1)=[];es ist immer der erste Eintrag.

Rufen Sie dann die Liste der Dateien in jedem Verzeichnis mit einer Schleife ab 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 Gibt das Verzeichnistrennzeichen für die Plattform zurück, auf der MATLAB ausgeführt wird.

Auf diese Weise erhalten Sie eine Liste von Dateinamen mit vollständigen Pfaden im Zellenarray- Dateinamellisten . Nicht die sauberste Lösung, ich weiß.


Aus Leistungsgründen möchte ich nicht genpath, es wird im Wesentlichen zweimal gesucht.
Gtker

2
Ein Nachteil bei der Verwendung von GENPATH besteht darin, dass nur Unterverzeichnisse enthalten sind, die im MATLAB-Pfad zulässig sind. Wenn Sie beispielsweise Verzeichnisse benannt haben private, werden diese nicht berücksichtigt.
Gnovice

1

Dies ist eine praktische Funktion zum Abrufen von Dateinamen mit dem angegebenen Format (normalerweise .mat) in einem Stammordner!

    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

In Ihrem Fall können Sie das folgende Snippet verwenden :)

filenames = getFilenames('D:/dic/**');
for i = 1:numel(filenames)
    filename = filenames{i};
    % do your job!
end

0

Mit wenig Modifikation, aber fast ähnlichem Ansatz, um den vollständigen Dateipfad jedes Unterordners zu erhalten

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  
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.