Como obter todos os arquivos em um diretório específico no MATLAB?


102

Preciso colocar todos esses arquivos sob D:\dice loop sobre eles para continuar a processar individualmente.

O MATLAB suporta este tipo de operações?

Isso pode ser feito em outros scripts como PHP, Python ...

Respostas:


130

Atualização: Dado que este post é bastante antigo, e modifiquei bastante este utilitário para meu próprio uso durante esse tempo, pensei que deveria postar uma nova versão. Meu mais novo código pode ser encontrado em The MathWorks File Exchange : dirPlus.m. Você também pode obter o código-fonte no GitHub .

Fiz uma série de melhorias. Ele agora oferece opções para preceder o caminho completo ou retornar apenas o nome do arquivo (incorporado de Doresoom e Oz Radiano ) e aplicar um padrão de expressão regular aos nomes de arquivo (incorporado de Peter D ). Além disso, adicionei a capacidade de aplicar uma função de validação a cada arquivo, permitindo que você os selecione com base em critérios diferentes de apenas seus nomes (ou seja, tamanho do arquivo, conteúdo, data de criação, etc.).


NOTA: Em versões mais recentes do MATLAB (R2016b e posterior), a dirfunção tem recursos de pesquisa recursiva! Portanto, você pode fazer isso para obter uma lista de todos os *.marquivos em todas as subpastas da pasta atual:

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

Código antigo: (para posteridade)

Esta é uma função que pesquisa recursivamente em todos os subdiretórios de um determinado diretório, coletando uma lista de todos os nomes de arquivo que encontra:

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

Depois de salvar a função acima em algum lugar do caminho do MATLAB, você pode chamá-la da seguinte maneira:

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

3
+1 - Ótima solução. Não sei se é necessário, mas se você inserir a linha: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); em sua solução entre a primeira definição fileList e a definição subDirs, ele retornará o caminho completo e o nome do arquivo para cada arquivo.
Doresoom

2
@Doresoom: Boa sugestão, embora eu tenha optado por usar FULLFILE, já que ele lida com a escolha do separador de arquivo para você (que é diferente no UNIX e no Windows). Além disso, você pode simplesmente fazer em fileList = strcat(dirName,filesep,fileList);vez de usar CELLFUN, embora possa acabar com separadores de arquivos desnecessários extras dessa forma, que FULLFILE também cuida para você.
gnovice

2
@gnovice, @Doreseoom - De acordo com mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , a ordem que 'dir' retorna depende do sistema operacional. Não tenho certeza do que acontece se, por exemplo, você definir a variável DOS DIRCMD para algo que muda a ordem. Octave lida com isso (. E .. ainda são os primeiros), mas eu não tenho o MATLAB para testar.
mtrw

2
@gnovice: Isso está além da questão do OP, mas achei útil incluir expressões regulares na função. 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 altere a assinatura da função para getAllFiles(dirName, pattern)(também da 2ª à última linha)
Peter D

1
Ótima resposta, obrigado!
Elaborei

25

Você está procurando dir para retornar o conteúdo do diretório.

Para repetir os resultados, você pode simplesmente fazer o seguinte:

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

Isso deve dar a você a saída no seguinte formato, por exemplo:

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

Você pode fazer uma pesquisa recursiva incluindo arquivos em subdiretórios, mas excluindo o próprio diretório?
Gtker de

Não de cabeça, não (não tenho mais acesso regular ao Matlab), mas isso pode ajudá-lo: mathworks.com/matlabcentral/fileexchange/…
James B

2
Como excluir .e ..?
Gtker de

5
@Runner: para excluir. e .., remova as duas primeiras entradas na saída de dir. Ou, caso você esteja procurando por um tipo de arquivo específico, execute dir('*.ext'), que exclui automaticamente os diretórios (a menos que terminem em .ext, é claro)
Jonas

14

Usei o código mencionado nesta ótima resposta e o expandi para oferecer suporte a 2 parâmetros adicionais que eu precisava no meu caso. Os parâmetros são extensões de arquivo para filtrar e um sinalizador que indica se deve concatenar o caminho completo para o nome do arquivo ou não.

Espero que esteja claro o suficiente e alguém ache benéfico.

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

Exemplo para executar o código:

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

8

Você pode usar regexp ou strcmp para eliminar .e .. ou pode usar o isdircampo se quiser apenas arquivos no diretório, não pastas.

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 combine as duas últimas linhas:

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

Para obter uma lista de pastas no diretório, exceto. e ..

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

A partir deste ponto, você deve ser capaz de lançar o código em um loop for aninhado e continuar pesquisando cada subpasta até que seus dirnames retornem uma célula vazia para cada subdiretório.


@Runner: Sim, se você usar alguns loops for e while ... mas estou com preguiça de implementar isso agora.
Doresoom

1 mesmo que não responda exatamente à pergunta, fornece uma maneira de selecionar os diretórios rapidamente.
jhfrontz

7

Essa resposta não responde diretamente à pergunta, mas pode ser uma boa solução fora da caixa.

Votei na solução do gnovice, mas quero oferecer outra solução: Use o comando dependente do sistema de seu sistema operacional:

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:

  • Muito rápido (no meu caso para um banco de dados de 18.000 arquivos no linux).
  • Você pode usar soluções bem testadas.
  • Você não precisa aprender ou reinventar uma nova sintaxe para selecionar os *.wavarquivos.

Negativo:

  • Você não é independente do sistema.
  • Você depende de uma única string que pode ser difícil de analisar.

3

Não conheço um método de função única para isso, mas você pode usar genpathpara recursar uma lista de subdiretórios apenas . Esta lista é retornada como uma string de diretórios delimitada por ponto-e-vírgula, então você terá que separá-la usando strread, ou seja,

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

Se você não quiser incluir o diretório fornecido, remova a primeira entrada de dirlist, ou seja, dirlist(1)=[];uma vez que é sempre a primeira entrada.

Em seguida, obtenha a lista de arquivos em cada diretório com um 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 retorna o separador de diretório para a plataforma na qual o MATLAB está sendo executado.

Isso fornece uma lista de nomes de arquivos com caminhos completos no filenamelist da matriz de células . Não é a solução mais legal, eu sei.


Por motivos de desempenho que não quero genpath, ele basicamente pesquisa duas vezes.
Gtker

2
Uma desvantagem de usar GENPATH é que ele incluirá apenas subdiretórios permitidos no caminho do MATLAB. Por exemplo, se você tiver diretórios nomeados private, eles não serão incluídos.
gnovice

1

Esta é uma função útil para obter nomes de arquivos, com o formato especificado (normalmente .mat) em uma pasta raiz!

    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

No seu caso, você pode usar o seguinte snippet :)

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

0

Com poucas modificações, mas uma abordagem quase semelhante para obter o caminho completo do arquivo de cada subpasta

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  
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.