¿Cómo obtener todos los archivos en un directorio específico en MATLAB?

102

Necesito poner todos esos archivos debajo D:\dicy recorrerlos para procesarlos individualmente.

¿MATLAB admite este tipo de operaciones?

Se puede hacer en otros scripts como PHP, Python ...

Gtker
fuente

Respuestas:

130

Actualización: dado que esta publicación es bastante antigua y he modificado mucho esta utilidad para mi propio uso durante ese tiempo, pensé que debería publicar una nueva versión. Mi código más reciente se puede encontrar en The MathWorks Archivo Cambio : dirPlus.m. También puede obtener la fuente de GitHub .

Hice una serie de mejoras. Ahora le brinda opciones para anteponer la ruta completa o devolver solo el nombre del archivo (incorporado de Doresoom y Oz Radiano ) y aplicar un patrón de expresión regular a los nombres de archivo (incorporado de Peter D ). Además, agregué la capacidad de aplicar una función de validación a cada archivo, lo que le permite seleccionarlos en función de criterios distintos a sus nombres (es decir, tamaño del archivo, contenido, fecha de creación, etc.).


NOTA: En las versiones más recientes de MATLAB (R2016b y posteriores), la dirfunción tiene capacidades de búsqueda recursiva. Entonces puede hacer esto para obtener una lista de todos los *.marchivos en todas las subcarpetas de la carpeta actual:

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

Código antiguo: (para la posteridad)

Aquí hay una función que busca de forma recursiva en todos los subdirectorios de un directorio determinado, recopilando una lista de todos los nombres de archivo que encuentra:

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

Después de guardar la función anterior en algún lugar de su ruta de MATLAB, puede llamarla de la siguiente manera:

fileList = getAllFiles('D:\dic');
gnovice
fuente
3
+1 - Gran solución. No sé si es necesario, pero si inserta la línea: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); en su solución entre la primera definición de fileList y la definición de subDirs, devolverá la ruta completa y el nombre de archivo para cada archivo.
Doresoom
2
@Doresoom: Buena sugerencia, aunque en su lugar fui con FULLFILE, ya que maneja la elección del separador de archivos por usted (que es diferente en UNIX y Windows). Además, puede hacerlo en fileList = strcat(dirName,filesep,fileList);lugar de usar CELLFUN, aunque puede terminar con separadores de archivos innecesarios adicionales de esa manera, que FULLFILE también se encarga de usted.
gnovice
2
@gnovice, @Doreseoom: de acuerdo con mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , el orden en que 'dir' devuelve depende del sistema operativo. No estoy seguro de qué sucede si, por ejemplo, establece la variable DIRCMD de DOS en algo que cambia el orden. Octave lo maneja bien (. Y .. todavía son los primeros) pero no tengo MATLAB para probar.
mtrw
2
@gnovice: Esto está más allá de la pregunta del OP, pero me pareció útil incorporar expresiones regulares en la función. 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 y cambie la firma de la función a getAllFiles(dirName, pattern)(también en la segunda a la última línea)
Peter D
1
Gran respuesta, gracias! He elaborado el código para admitir 2 parámetros adicionales - stackoverflow.com/a/26449095/69555
Oz Radiano
25

Está buscando dir para devolver el contenido del directorio.

Para recorrer los resultados, simplemente puede hacer lo siguiente:

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

Esto debería darle una salida en el siguiente formato, por ejemplo:

name: 'my_file'
date: '01-Jan-2010 12:00:00'
bytes: 56
isdir: 0
datenum: []
James B
fuente
¿Puede hacer que busque de forma recursiva incluyendo archivos en subdirectorios pero excluyendo el directorio mismo?
Gtker
No en la parte superior de mi cabeza, no (ya no tengo acceso regular a Matlab), pero esto puede ayudarlo: mathworks.com/matlabcentral/fileexchange/…
James B
2
¿Cómo excluir .y ..?
Gtker
5
@Runner: para excluir. y .., elimine las dos primeras entradas en la salida de dir. O, en caso de que esté buscando un tipo de archivo específico, ejecute dir('*.ext'), lo que excluye automáticamente los directorios (a menos que terminen en .ext, por supuesto)
Jonas
14

Usé el código mencionado en esta gran respuesta y lo expandí para admitir 2 parámetros adicionales que necesitaba en mi caso. Los parámetros son extensiones de archivo para filtrar y una bandera que indica si concatenar la ruta completa al nombre del archivo o no.

Espero que sea lo suficientemente claro y que alguien lo encuentre beneficioso.

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

Ejemplo para ejecutar el código:

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

Puede usar regexp o strcmp para eliminar .y .. O puede usar el isdircampo si solo desea archivos en el directorio, no carpetas.

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

o combine las dos últimas líneas:

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

Para obtener una lista de carpetas en el directorio excluyendo. y ...

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

Desde este punto, debería poder lanzar el código en un bucle for anidado y continuar buscando en cada subcarpeta hasta que sus nombres de directorio devuelvan una celda vacía para cada subdirectorio.

Doresoom
fuente
@Runner: Lo hace si usa algunos bucles for y while ... pero soy demasiado vago para implementar eso en este momento.
Doresoom
+1 aunque no responde exactamente a la pregunta, proporciona una manera de eliminar los directorios rápidamente.
jhfrontz
7

Esta respuesta no responde directamente a la pregunta, pero puede ser una buena solución fuera de la caja.

Yo voté a favor de la solución de gnovice, pero quiero ofrecer otra solución: use el comando dependiente del sistema de su 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:

  • Muy rápido (en mi caso para una base de datos de 18000 archivos en Linux).
  • Puede utilizar soluciones bien probadas.
  • No es necesario que aprenda o reinvente una nueva sintaxis para seleccionar *.wavarchivos ie .

Negativo:

  • No eres independiente del sistema.
  • Depende de una sola cadena que puede ser difícil de analizar.
Lukas
fuente
3

No conozco un método de función única para esto, pero puede usarlo genpathpara recurrir solo a una lista de subdirectorios . Esta lista se devuelve como una cadena de directorios delimitada por punto y coma, por lo que tendrá que separarla usando strread, es decir

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

Si no desea incluir el directorio dado, elimine la primera entrada de dirlist, es decir, dirlist(1)=[];ya que siempre es la primera entrada.

Luego obtenga la lista de archivos en cada directorio con un bucle 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 devuelve el separador de directorio para la plataforma en la que se ejecuta MATLAB.

Esto le da una lista de nombres de archivos con rutas completas en la serie de células filenamelist . No es la mejor solución, lo sé.

JS Ng
fuente
Por motivos de rendimiento que no quiero genpath, básicamente busca dos veces.
Gtker
2
Un inconveniente de usar GENPATH es que solo incluirá los subdirectorios que están permitidos en la ruta de MATLAB. Por ejemplo, si tiene directorios nombrados private, no se incluirán.
gnovice
1

Esta es una función útil para obtener nombres de archivos, con el formato especificado (generalmente .mat) en una carpeta raíz.

    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

En su caso, puede utilizar el siguiente fragmento :)

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

Con pocas modificaciones pero un enfoque casi similar para obtener la ruta completa del archivo de cada subcarpeta

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  
Spandan
fuente