MATLAB'da belirli bir dizin altındaki tüm dosyalar nasıl elde edilir?


102

D:\dicTek tek işlemek için tüm bu dosyaları altına almam ve üzerlerinden geçirmem gerekiyor.

MATLAB bu tür işlemleri destekliyor mu?

PHP, Python gibi diğer betiklerde yapılabilir ...

Yanıtlar:


130

Güncelleme: Bu gönderinin oldukça eski olduğu ve bu yardımcı programı bu süre zarfında kendi kullanımım için çok değiştirdiğim göz önüne alındığında, yeni bir sürüm göndermem gerektiğini düşündüm. Benim yeni kod bulunabilir MathWorks Dosya Değişimi : dirPlus.m. Kaynağı GitHub'dan da alabilirsiniz .

Bir takım iyileştirmeler yaptım. Şimdi size tam yolu başa ekleme veya yalnızca dosya adını ( Doresoom ve Oz Radiano'dan alınmıştır ) döndürme ve dosya adlarına ( Peter D' den alınmıştır ) düzenli bir ifade modeli uygulama seçenekleri sunar . Ek olarak, her dosyaya bir doğrulama işlevi uygulama olanağı ekledim, bu da onları yalnızca adlarından başka kriterlere (yani dosya boyutu, içerik, oluşturma tarihi vb.) Göre seçmenize olanak tanıdı.


NOT: MATLAB'ın daha yeni sürümlerinde (R2016b ve sonrası), dirişlevin özyinelemeli arama yetenekleri vardır! Dolayısıyla *.m, geçerli klasörün tüm alt klasörlerindeki tüm dosyaların bir listesini almak için bunu yapabilirsiniz :

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

Eski kod: (gelecek nesil için)

Belirli bir dizinin tüm alt dizinlerinde yinelemeli olarak arama yapan ve bulduğu tüm dosya adlarının bir listesini toplayan bir işlev:

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

Yukarıdaki işlevi MATLAB yolunuzda bir yere kaydettikten sonra, aşağıdaki şekilde çağırabilirsiniz:

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

3
+1 - Harika çözüm. Gerekli olup olmadığını bilmiyorum, ancak şu satırı eklerseniz: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); ilk fileList tanımı ile subDirs tanımı arasındaki çözümünüze, her dosya için tam yolu ve dosya adını döndürecektir.
Doresoom

2
@Doresoom: İyi bir öneri, bunun yerine FULLFILE kullanmaya devam etsem de, sizin için dosya ayırıcı seçimini yaptığından (UNIX ve Windows'ta farklıdır). Ayrıca, fileList = strcat(dirName,filesep,fileList);CELLFUN kullanmak yerine sadece yapabilirsiniz , ancak bu şekilde fazladan gereksiz dosya ayırıcılarla karşılaşabilirsiniz, FULLFILE sizin için de ilgilenir.
gnovice

2
@gnovice, @Doreseoom - mathworks.com/access/helpdesk/help/techdoc/ref/dir.html 'e göre,' dir'in döndürdüğü sıra işletim sistemine bağlıdır. Örneğin, DOS DIRCMD değişkenini sırayı değiştiren bir şeye ayarlarsanız ne olur emin değilim. Octave bunu hallediyor (. Ve .. hala ilk sırada) ama test etmek için MATLAB yok.
mtrw

2
@gnovice: Bu, OP'nin sorusunun ötesinde, ancak işleve düzenli ifadeler eklemeyi yararlı buldum. 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 ve işlev imzasını şu şekilde değiştirin getAllFiles(dirName, pattern)(ayrıca
Peter D

1
Harika cevap, teşekkürler! 2 ek parametreyi desteklemek için kodu detaylandırdım - stackoverflow.com/a/26449095/69555
Oz Radiano

25

Dizin içeriğini döndürmek için dir'i arıyorsunuz .

Sonuçların üzerinden geçmek için aşağıdakileri yapmanız yeterlidir:

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

Bu size aşağıdaki formatta çıktı vermelidir, örneğin:

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

Alt dizinlerdeki dosyalar dahil, ancak dizinin kendisini hariç tutarak yinelemeli olarak aramasını sağlayabilir misiniz?
Gtker

Kafamın tepesinden değil, hayır (artık Matlab'a
James B

2
Nasıl hariç tutulur .ve ..?
Gtker

5
@ Runner: Hariç tutmak için. ve .., dizinin çıktısındaki ilk iki girişi kaldırın. Veya, belirli bir dosya türü arıyorsanız dir('*.ext'), dizinleri otomatik olarak hariç tutan çalıştır (tabii ki .ext ile bitmedikçe)
Jonas

14

Bu harika cevapta bahsedilen kodu kullandım ve benim durumumda ihtiyacım olan 2 ek parametreyi destekleyecek şekilde genişlettim. Parametreler, filtrelenecek dosya uzantıları ve dosyanın adının tam yolunun birleştirilip birleştirilmeyeceğini belirten bir işarettir.

Umarım yeterince açıktır ve birisi bunu faydalı bulacaktır.

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

Kodu çalıştırmak için örnek:

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

8

Sen regexp'in kullanabilir veya ortadan kaldırmak için strcmp edebilir .ve .. Yoksa kullanabilirsiniz isdirsadece dizinde değil, klasörleri dosyaları isterseniz alanını.

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

veya son iki satırı birleştirin:

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

Hariç dizindeki klasörlerin listesi için. ve ..

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

Bu noktadan itibaren, kodu yuvalanmış bir for döngüsüne atabilmeli ve dizin adlarınız her alt dizin için boş bir hücre döndürene kadar her alt klasörü aramaya devam edebilmelisiniz.


@Runner: Bazılarını for and while döngüleri kullanırsanız yapar ... ama şimdi bunu uygulamak için tembelim.
Doresoom

+1, soruyu tam olarak cevaplamasa da, dizinleri hızlı bir şekilde ayırmanın bir yolunu sağlar.
jhfrontz

7

Bu cevap, soruyu doğrudan cevaplamaz, ancak kutunun dışında iyi bir çözüm olabilir.

Gnovice'nin çözümüne oy verdim, ancak başka bir çözüm sunmak istiyorum: İşletim sisteminizin sisteme bağlı komutunu kullanın:

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.

Pozitif:

  • Çok hızlı (benim durumumda linux üzerinde 18000 dosyalık bir veritabanı için).
  • İyi test edilmiş çözümleri kullanabilirsiniz.
  • İe *.wavdosyalarını seçmek için yeni bir sözdizimi öğrenmenize veya yeniden icat etmenize gerek yoktur .

Olumsuz:

  • Sistemden bağımsız değilsiniz.
  • Ayrıştırılması zor olabilecek tek bir dizeye güveniyorsunuz.

3

Bunun için tek işlevli bir yöntem bilmiyorum, ancak yalnızca alt dizinleringenpath bir listesini yinelemek için kullanabilirsiniz . Bu liste, noktalı virgülle ayrılmış dizinler dizisi olarak döndürülür, bu nedenle onu strread kullanarak ayırmanız gerekir, yani

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

Verilen dizini dahil etmek istemiyorsanız, ilk girdiyi kaldırın dirlist, yani dirlist(1)=[];her zaman ilk girdi olduğu için.

Sonra her dizindeki dosyaların listesini bir döngü ile alın 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 MATLAB'ın çalıştığı platform için dizin ayırıcısını döndürür.

Bu size hücre dizisi dosya listesindeki tam yolları içeren dosya adlarının bir listesini verir . En iyi çözüm değil, biliyorum.


Performans nedeniyle istemiyorum genpath, esasen iki kez arar.
Gtker

2
GENPATH kullanmanın bir dezavantajı, yalnızca MATLAB yolunda izin verilen alt dizinleri içerecek olmasıdır. Örneğin, adlandırılmış dizinleriniz varsa private, bunlar dahil edilmeyecektir.
gnovice

1

Bu, .matbir kök klasörde belirtilen formatla (genellikle ) dosya adları almak için kullanışlı bir işlevdir !

    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

Sizin durumunuzda aşağıdaki parçacığı kullanabilirsiniz :)

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

0

Her alt klasörün tam dosya yolunu elde etmek için çok az değişiklik, ancak neredeyse benzer bir yaklaşımla

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  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.