Comment obtenir tous les fichiers dans un répertoire spécifique dans MATLAB?


102

Je dois récupérer tous ces fichiers D:\dicet les parcourir pour les traiter individuellement.

MATLAB prend-il en charge ce type d'opérations?

Cela peut être fait dans d'autres scripts comme PHP, Python ...

Réponses:


130

Mise à jour: Étant donné que cet article est assez ancien et que j'ai beaucoup modifié cet utilitaire pour mon propre usage pendant cette période, j'ai pensé que je devrais publier une nouvelle version. Mon code le plus récent se trouve sur The MathWorks Exchange fichier : dirPlus.m. Vous pouvez également obtenir la source sur GitHub .

J'ai apporté un certain nombre d'améliorations. Il vous donne maintenant des options pour ajouter le chemin d'accès complet ou renvoyer uniquement le nom du fichier (incorporé à partir de Doresoom et Oz Radiano ) et appliquer un modèle d'expression régulière aux noms de fichier (incorporé à partir de Peter D ). De plus, j'ai ajouté la possibilité d'appliquer une fonction de validation à chaque fichier, vous permettant de les sélectionner en fonction de critères autres que leurs noms (ie taille du fichier, contenu, date de création, etc.).


REMARQUE: dans les versions plus récentes de MATLAB (R2016b et versions ultérieures), la dirfonction a des capacités de recherche récursive! Vous pouvez donc le faire pour obtenir une liste de tous les *.mfichiers de tous les sous-dossiers du dossier actuel:

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

Ancien code: (pour la postérité)

Voici une fonction qui recherche récursivement dans tous les sous-répertoires d'un répertoire donné, en collectant une liste de tous les noms de fichiers trouvés:

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

Après avoir enregistré la fonction ci-dessus quelque part sur votre chemin MATLAB, vous pouvez l'appeler de la manière suivante:

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

3
+1 - Excellente solution. Je ne sais pas si c'est nécessaire, mais si vous insérez la ligne: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); dans votre solution entre la première définition de fileList et la définition de sous-répertoires, il renverra le chemin complet et le nom de fichier pour chaque fichier.
Doresoom

2
@Doresoom: Bonne suggestion, même si j'ai opté pour FULLFILE à la place, car il gère le choix du séparateur de fichiers pour vous (ce qui est différent sous UNIX et Windows). De plus, vous pouvez simplement le faire fileList = strcat(dirName,filesep,fileList);au lieu d'utiliser CELLFUN, bien que vous puissiez vous retrouver avec des séparateurs de fichiers inutiles supplémentaires de cette façon, que FULLFILE prend également en charge pour vous.
gnovice

2
@gnovice, @Doreseoom - Selon mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , l'ordre renvoyé par «dir» dépend du système d'exploitation. Je ne suis pas sûr de ce qui se passe si, par exemple, vous définissez la variable DOS DIRCMD sur quelque chose qui change l'ordre. Octave le gère bien (. Et .. sont toujours les premiers) mais je n'ai pas MATLAB à tester.
mtrw

2
@gnovice: Cela dépasse la question du PO, mais j'ai trouvé utile d'intégrer des expressions régulières dans la fonction. 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 et changez la signature de la fonction en getAllFiles(dirName, pattern)(également dans la 2e à la dernière ligne)
Peter D

1
Excellente réponse, merci! J'ai élaboré le code pour prendre en charge 2 paramètres supplémentaires - stackoverflow.com/a/26449095/69555
Oz Radiano

25

Vous recherchez dir pour renvoyer le contenu du répertoire.

Pour parcourir les résultats, vous pouvez simplement faire ce qui suit:

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

Cela devrait vous donner une sortie dans le format suivant, par exemple:

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

Pouvez-vous faire une recherche récursive en incluant les fichiers dans les sous-répertoires mais en excluant le répertoire lui-même?
Gtker

Pas par surprise
James B

2
Comment exclure .et ..?
Gtker

5
@Runner: à exclure. et .., supprimez les deux premières entrées de la sortie de dir. Ou, si vous recherchez un type de fichier spécifique, exécutez dir('*.ext'), qui exclut automatiquement les répertoires (à moins qu'ils ne se terminent par .ext, bien sûr)
Jonas

14

J'ai utilisé le code mentionné dans cette excellente réponse et l'ai étendu pour prendre en charge 2 paramètres supplémentaires dont j'avais besoin dans mon cas. Les paramètres sont des extensions de fichier sur lesquelles filtrer et un indicateur indiquant s'il faut concaténer le chemin complet vers le nom du fichier ou non.

J'espère que c'est assez clair et que quelqu'un le trouvera bénéfique.

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

Exemple pour exécuter le code:

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

8

Vous pouvez utiliser regexp ou strcmp pour éliminer .et .. ou vous pouvez utiliser le isdirchamp si vous ne voulez que des fichiers dans le répertoire, pas des dossiers.

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

ou combinez les deux dernières lignes:

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

Pour une liste des dossiers dans le répertoire à l'exclusion de. et ..

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

À partir de ce moment, vous devriez être en mesure de lancer le code dans une boucle for imbriquée et de continuer à rechercher dans chaque sous-dossier jusqu'à ce que vos noms de répertoire renvoient une cellule vide pour chaque sous-répertoire.


@Runner: C'est le cas si vous utilisez des boucles for et while ... mais je suis trop paresseux pour l'implémenter maintenant.
Doresoom

+1 même s'il ne répond pas exactement à la question, il fournit un moyen d'éliminer rapidement les répertoires.
jhfrontz

7

Cette réponse ne répond pas directement à la question mais peut être une bonne solution en dehors de la boîte.

J'ai voté pour la solution de gnovice, mais je souhaite proposer une autre solution: utilisez la commande dépendante du système de votre système d'exploitation:

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.

Positif:

  • Très rapide (dans mon cas pour une base de données de 18000 fichiers sous linux).
  • Vous pouvez utiliser des solutions bien testées.
  • Vous n'avez pas besoin d'apprendre ou de réinventer une nouvelle syntaxe pour sélectionner des *.wavfichiers ie .

Négatif:

  • Vous n'êtes pas indépendant du système.
  • Vous comptez sur une seule chaîne qui peut être difficile à analyser.

3

Je ne connais pas de méthode à fonction unique pour cela, mais vous pouvez utiliser genpathpour récurer une liste de sous - répertoires uniquement . Cette liste est renvoyée sous la forme d'une chaîne de répertoires délimitée par des points-virgules, vous devrez donc la séparer en utilisant strread, ie

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

Si vous ne voulez pas inclure le répertoire donné, supprimez la première entrée de dirlist, c'est-à-dire dirlist(1)=[];qu'il s'agit toujours de la première entrée.

Ensuite, récupérez la liste des fichiers dans chaque répertoire avec un fichier en boucle 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 renvoie le séparateur de répertoire de la plate-forme sur laquelle MATLAB s'exécute.

Cela vous donne une liste de noms avec les chemins complets dans la matrice de cellules filenamelist . Pas la meilleure solution, je sais.


Pour des raisons de performances que je ne veux pas genpath, il recherche essentiellement deux fois.
Gtker

2
Un inconvénient de l'utilisation de GENPATH est qu'il n'inclura que les sous-répertoires autorisés sur le chemin MATLAB. Par exemple, si vous avez des répertoires nommés private, ils ne seront pas inclus.
gnovice

1

C'est une fonction pratique pour obtenir des noms de fichiers, avec le format spécifié (généralement .mat) dans un dossier racine!

    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

Dans votre cas, vous pouvez utiliser l'extrait suivant :)

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

0

Avec peu de modifications mais une approche presque similaire pour obtenir le chemin complet du fichier de chaque sous-dossier

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  
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.