Come ottenere tutti i file in una directory specifica in MATLAB?


102

Ho bisogno di recuperare tutti quei file D:\dice di passarci sopra per elaborarli ulteriormente individualmente.

MATLAB supporta questo tipo di operazioni?

Può essere fatto in altri script come PHP, Python ...

Risposte:


130

Aggiornamento: dato che questo post è piuttosto vecchio e ho modificato molto questa utility per il mio uso durante quel periodo, ho pensato di pubblicare una nuova versione. La mia più recente codice può essere trovato sulla The MathWorks file scambio : dirPlus.m. Puoi anche ottenere il codice sorgente da GitHub .

Ho apportato una serie di miglioramenti. Ora offre opzioni per anteporre il percorso completo o restituire solo il nome del file (incorporato da Doresoom e Oz Radiano ) e applicare un modello di espressione regolare ai nomi dei file (incorporato da Peter D ). Inoltre, ho aggiunto la possibilità di applicare una funzione di convalida a ciascun file, permettendoti di selezionarli in base a criteri diversi dal solo nome (ad esempio dimensione del file, contenuto, data di creazione, ecc.).


NOTA: nelle versioni più recenti di MATLAB (R2016b e successive), la dirfunzione ha capacità di ricerca ricorsiva! Quindi puoi farlo per ottenere un elenco di tutti i *.mfile in tutte le sottocartelle della cartella corrente:

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

Vecchio codice: (per i posteri)

Ecco una funzione che ricerca ricorsivamente in tutte le sottodirectory di una determinata directory, raccogliendo un elenco di tutti i nomi di file che trova:

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

Dopo aver salvato la funzione sopra da qualche parte nel tuo percorso MATLAB, puoi chiamarla nel modo seguente:

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

3
+1 - Ottima soluzione. Non so se sia necessario, ma se inserisci la riga: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); nella tua soluzione tra la prima definizione di fileList e la definizione di subDirs, restituirà il percorso completo e il nome del file per ogni file.
Doresoom

2
@ Doresoom: buon suggerimento, anche se sono andato usando FULLFILE invece, poiché gestisce la scelta del separatore di file per te (che è diverso su UNIX e Windows). Inoltre, potresti semplicemente fare fileList = strcat(dirName,filesep,fileList);invece di usare CELLFUN, anche se in questo modo potresti ritrovarti con separatori di file non necessari extra, di cui FULLFILE si prende cura anche per te.
gnovice

2
@gnovice, @Doreseoom - Secondo mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , l'ordine restituito da "dir" dipende dal sistema operativo. Non sono sicuro di cosa succede se, ad esempio, imposti la variabile DOS DIRCMD su qualcosa che cambia l'ordine. Octave lo gestisce bene (. E .. sono ancora i primi) ma non ho MATLAB da testare.
mtrw

2
@gnovice: questo va oltre la domanda dell'OP, ma ho trovato utile incorporare espressioni regolari nella funzione. 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 e cambia la firma della funzione in getAllFiles(dirName, pattern)(anche nella penultima riga)
Peter D

1
Ottima risposta, grazie! Ho elaborato il codice per supportare 2 parametri aggiuntivi - stackoverflow.com/a/26449095/69555
Oz Radiano

25

Stai cercando dir per restituire il contenuto della directory.

Per scorrere i risultati, puoi semplicemente fare quanto segue:

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

Questo dovrebbe darti l'output nel seguente formato, ad esempio:

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

Puoi fare in modo che la ricerca ricorsiva includendo i file nelle sottodirectory ma escludendo la directory stessa?
Gtker

Non fuori dalla mia testa, no (non ho più accesso regolare a Matlab), ma questo potrebbe aiutarti: mathworks.com/matlabcentral/fileexchange/…
James B

2
Come escludere .e ..?
Gtker

5
@ Runner: da escludere. e .., rimuovere le prime due voci nell'output di dir. Oppure, nel caso tu stia cercando un tipo di file specifico, esegui dir('*.ext'), che esclude automaticamente le directory (a meno che non finiscano in .ext, ovviamente)
Jonas

14

Ho usato il codice menzionato in questa ottima risposta e l'ho espanso per supportare 2 parametri aggiuntivi di cui avevo bisogno nel mio caso. I parametri sono estensioni di file su cui filtrare e un flag che indica se concatenare o meno il percorso completo al nome del file.

Spero che sia abbastanza chiaro e che qualcuno lo trovi utile.

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

Esempio per eseguire il codice:

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

8

Puoi usare regexp o strcmp per eliminare .e .. Oppure puoi usare il isdircampo se vuoi solo file nella directory, non cartelle.

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

oppure combina le ultime due righe:

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

Per un elenco di cartelle nella directory escluse. e ..

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

Da questo punto, dovresti essere in grado di lanciare il codice in un ciclo for annidato e continuare a cercare in ogni sottocartella finché i tuoi dirnames non restituiscono una cella vuota per ogni sottodirectory.


@ Runner: lo fa se usi alcuni cicli for e while ... ma sono troppo pigro per implementarlo adesso.
Doresoom

+1 anche se non risponde esattamente alla domanda, fornisce un modo per selezionare rapidamente le directory.
jhfrontz

7

Questa risposta non risponde direttamente alla domanda, ma può essere una buona soluzione fuori dagli schemi.

Ho votato positivamente la soluzione di gnovice, ma voglio offrire un'altra soluzione: usa il comando dipendente dal sistema del tuo sistema operativo:

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.

Positivo:

  • Molto veloce (nel mio caso per un database di 18000 file su Linux).
  • Puoi usare soluzioni ben testate.
  • Non è necessario imparare o reinventare una nuova sintassi per selezionare i *.wavfile, ad esempio .

Negativo:

  • Non sei indipendente dal sistema.
  • Ti affidi a una singola stringa che potrebbe essere difficile da analizzare.

3

Non conosco un metodo a funzione singola per questo, ma puoi usarlo genpathper ricorrere solo a un elenco di sottodirectory . Questo elenco viene restituito come una stringa di directory delimitata da punto e virgola, quindi dovrai separarlo usando strread, cioè

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

Se non vuoi includere la directory data, rimuovi la prima voce di dirlist, cioè dirlist(1)=[];poiché è sempre la prima voce.

Quindi ottieni l'elenco dei file in ciascuna directory con un loop 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 restituisce il separatore di directory per la piattaforma su cui MATLAB è in esecuzione.

Questo ti dà un elenco di nomi di file con percorsi completi nell'array di celle filenamelist . Non è la soluzione più pulita, lo so.


Per motivi di prestazioni non voglio genpath, essenzialmente cerca due volte.
Gtker

2
Uno svantaggio dell'utilizzo di GENPATH è che includerà solo le sottodirectory consentite nel percorso MATLAB. Ad esempio, se sono presenti directory denominate private, non verranno incluse.
gnovice

1

Questa è una funzione utile per ottenere i nomi dei file, con il formato specificato (di solito .mat) in una cartella principale!

    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

Nel tuo caso, puoi utilizzare il seguente snippet :)

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

0

Con poche modifiche ma un approccio quasi simile per ottenere il percorso completo del file di ogni sottocartella

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  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.