Jak uzyskać wszystkie pliki w określonym katalogu w MATLAB?

102

Muszę umieścić wszystkie te pliki pod D:\dicspodem i zapętlić je w celu dalszego przetwarzania indywidualnie.

Czy MATLAB obsługuje tego typu operacje?

Można to zrobić w innych skryptach, takich jak PHP, Python ...

Gtker
źródło

Odpowiedzi:

130

Aktualizacja: Biorąc pod uwagę, że ten post jest dość stary, aw tym czasie bardzo zmodyfikowałem to narzędzie na własny użytek, pomyślałem, że powinienem opublikować nową wersję. Mój najnowszy kod można znaleźć na MathWorks File Exchange : dirPlus.m. Możesz również pobrać źródło z GitHub .

Wprowadziłem szereg ulepszeń. Teraz daje możliwość dołączenia pełnej ścieżki lub zwrócenia samej nazwy pliku ( zawartej w Doresoom i Oz Radiano ) i zastosowania wzorca wyrażenia regularnego do nazw plików (zaczerpnięty z Petera D ). Dodatkowo dodałem możliwość zastosowania funkcji walidacji do każdego pliku, co pozwala na ich wybór na podstawie innych kryteriów niż tylko ich nazwy (np. Rozmiar pliku, zawartość, data utworzenia itp.).


UWAGA: W nowszych wersjach MATLAB (R2016b i nowsze) dirfunkcja ma możliwość wyszukiwania rekurencyjnego! Możesz więc to zrobić, aby uzyskać listę wszystkich *.mplików we wszystkich podfolderach bieżącego folderu:

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

Stary kod: (dla potomnych)

Oto funkcja, która przeszukuje rekurencyjnie wszystkie podkatalogi danego katalogu, zbierając listę wszystkich znalezionych nazw plików:

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

Po zapisaniu powyższej funkcji gdzieś na swojej ścieżce MATLAB-a możesz ją wywołać w następujący sposób:

fileList = getAllFiles('D:\dic');
gnovice
źródło
3
+1 - Świetne rozwiązanie. Nie wiem, czy jest to konieczne, ale jeśli wstawisz linię: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); w rozwiązaniu między pierwszą definicją fileList a definicją subDirs, zwróci pełną ścieżkę i nazwę pliku dla każdego pliku.
Doresoom
2
@Doresoom: Dobra sugestia, chociaż zamiast tego zdecydowałem się na użycie FULLFILE, ponieważ obsługuje on wybór separatora plików (który jest inny w systemach UNIX i Windows). Możesz też po prostu zrobić to fileList = strcat(dirName,filesep,fileList);zamiast używać CELLFUN, chociaż w ten sposób możesz skończyć z dodatkowymi niepotrzebnymi separatorami plików, którymi FULLFILE również zajmie się tobą.
gnovice
2
@gnovice, @Doreseoom - Według mathworks.com/access/helpdesk/help/techdoc/ref/dir.html kolejność zwracania „dir” zależy od systemu operacyjnego. Nie jestem pewien, co się stanie, jeśli na przykład ustawisz zmienną DOS DIRCMD na coś, co zmienia kolejność. Octave radzi sobie z tym ok (. I ... nadal są pierwsze), ale nie mam MATLAB-a do testowania.
mtrw
2
@gnovice: To jest poza kwestią OP, ale uznałem za przydatne wbudowanie wyrażeń regularnych do funkcji. 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 i zmień sygnaturę funkcji na getAllFiles(dirName, pattern)(również w drugiej do ostatniej linii)
Peter D
1
Świetna odpowiedź, dzięki! Opracowałem kod do obsługi 2 dodatkowych parametrów - stackoverflow.com/a/26449095/69555
Oz Radiano
25

Szukasz reż wrócić zawartość katalogów.

Aby zapętlić wyniki, możesz po prostu wykonać następujące czynności:

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

Powinno to dać wynik w następującym formacie, np .:

name: 'my_file'
date: '01-Jan-2010 12:00:00'
bytes: 56
isdir: 0
datenum: []
James B.
źródło
Czy możesz sprawić, by przeszukiwał cyklicznie, włączając pliki w podkatalogach, ale wyłączając sam katalog?
Gtker
Nie z góry, nie (nie mam już stałego dostępu do Matlab), ale to może ci pomóc: mathworks.com/matlabcentral/fileexchange/…
James B
2
Jak wykluczyć .i ..?
Gtker
5
@Runner: do wykluczenia. i .., usuń pierwsze dwa wpisy z wyjścia dir. Lub, jeśli szukasz określonego typu pliku, uruchom dir('*.ext'), co automatycznie wyklucza katalogi (chyba że kończą się na .ext, oczywiście)
Jonas
14

Użyłem kodu wymienionego w tej świetnej odpowiedzi i rozszerzyłem go tak, aby obsługiwał 2 dodatkowe parametry, których potrzebowałem w moim przypadku. Parametry to rozszerzenia plików do filtrowania i flaga wskazująca, czy połączyć pełną ścieżkę do nazwy pliku, czy nie.

Mam nadzieję, że jest to wystarczająco jasne i komuś się przyda.

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

Przykład uruchomienia kodu:

fileList = getAllFiles(dirName, '*.xml', 0); %#0 is false obviously
Oz Radiano
źródło
8

Możesz użyć regexp lub strcmp, aby wyeliminować .i .. lub możesz użyć tego isdirpola, jeśli chcesz tylko pliki w katalogu, a nie foldery.

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

lub połącz ostatnie dwie linie:

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

Aby uzyskać listę folderów w katalogu z wyłączeniem plików. i ..

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

Od tego momentu powinieneś być w stanie wrzucić kod do zagnieżdżonej pętli for i kontynuować przeszukiwanie każdego podfolderu, aż dirnames zwróci pustą komórkę dla każdego podkatalogu.

Doresoom
źródło
@Runner: Robi się, jeśli używasz pętli for i while ... ale jestem zbyt leniwy, aby to teraz zaimplementować.
Doresoom
+1, mimo że nie jest to dokładna odpowiedź na pytanie, zapewnia sposób na szybkie usunięcie katalogów.
jhfrontz
7

Ta odpowiedź nie odpowiada bezpośrednio na pytanie, ale może być dobrym rozwiązaniem poza polem.

Głosowałem za rozwiązaniem gnovice, ale chcę zaoferować inne rozwiązanie: użyj polecenia zależnego od systemu w swoim systemie operacyjnym:

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.

Pozytywny:

  • Bardzo szybko (w moim przypadku dla bazy danych zawierającej 18000 plików na Linuksie).
  • Możesz skorzystać z dobrze sprawdzonych rozwiązań.
  • Nie musisz uczyć się ani wymyślać nowej składni, aby wybierać np *.wav. Pliki.

Negatywny:

  • Nie jesteś niezależny od systemu.
  • Polegasz na jednym ciągu, który może być trudny do przeanalizowania.
Lukas
źródło
3

Nie znam metody jednofunkcyjnej do tego, ale możesz użyć genpathdo powtórzenia tylko listy podkatalogów . Ta lista jest zwracana jako ciąg katalogów rozdzielany średnikami, więc będziesz musiał oddzielić ją za pomocą strread, tj.

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

Jeśli nie chcesz dołączać podanego katalogu, usuń pierwszy wpis dirlist, tj. dirlist(1)=[];Ponieważ jest to zawsze pierwszy wpis.

Następnie pobierz listę plików w każdym katalogu z zapętlonym 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 zwraca separator katalogów dla platformy, na której działa MATLAB.

W ten sposób otrzymasz listę nazw plików z pełnymi ścieżkami w tablicy komórek filenamelist . Wiem, że nie jest to najładniejsze rozwiązanie.

JS Ng
źródło
Ze względu na wydajność, którego nie chcę genpath, zasadniczo przeszukuje dwukrotnie.
Gtker
2
Jedną z wad korzystania z GENPATH jest to, że będzie zawierał tylko podkatalogi, które są dozwolone w ścieżce MATLAB. Na przykład, jeśli masz nazwane katalogi private, nie zostaną one uwzględnione.
gnovice
1

Jest to przydatna funkcja do pobierania nazw plików w określonym formacie (zwykle .mat) w folderze głównym!

    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

W twoim przypadku możesz użyć następującego fragmentu :)

filenames = getFilenames('D:/dic/**');
for i = 1:numel(filenames)
    filename = filenames{i};
    % do your job!
end
Tak
źródło
0

Z niewielkimi modyfikacjami, ale prawie podobnym podejściem, aby uzyskać pełną ścieżkę do każdego podfolderu

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
źródło