Bagaimana cara mendapatkan semua file di bawah direktori tertentu di MATLAB?

102

Saya perlu mendapatkan semua file itu di bawah D:\dicdan mengulanginya untuk diproses lebih lanjut satu per satu.

Apakah MATLAB mendukung operasi semacam ini?

Itu dapat dilakukan di skrip lain seperti PHP, Python ...

Gtker
sumber

Jawaban:

130

Pembaruan: Mengingat bahwa posting ini cukup lama, dan saya telah banyak memodifikasi utilitas ini untuk penggunaan saya sendiri selama waktu itu, saya pikir saya harus memposting versi baru. Kode terbaru saya dapat ditemukan di The MathWorks Berkas Efek : dirPlus.m. Anda juga bisa mendapatkan sumbernya dari GitHub .

Saya membuat sejumlah perbaikan. Sekarang memberi Anda opsi untuk menambahkan jalur lengkap atau mengembalikan hanya nama file (digabungkan dari Doresoom dan Oz Radiano ) dan menerapkan pola ekspresi reguler ke nama file (digabungkan dari Peter D ). Selain itu, saya menambahkan kemampuan untuk menerapkan fungsi validasi ke setiap file, memungkinkan Anda memilihnya berdasarkan kriteria selain hanya namanya (yaitu ukuran file, konten, tanggal pembuatan, dll.).


CATATAN: Dalam versi MATLAB yang lebih baru (R2016b dan yang lebih baru), dirfungsi tersebut memiliki kemampuan pencarian rekursif! Jadi, Anda dapat melakukan ini untuk mendapatkan daftar semua *.mfile di semua subfolder dari folder saat ini:

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

Kode lama: (untuk anak cucu)

Berikut adalah fungsi yang mencari secara rekursif melalui semua subdirektori dari direktori tertentu, mengumpulkan daftar semua nama file yang ditemukannya:

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

Setelah menyimpan fungsi di atas di suatu tempat di jalur MATLAB Anda, Anda dapat memanggilnya dengan cara berikut:

fileList = getAllFiles('D:\dic');
gnovice
sumber
3
+1 - Solusi hebat. Saya tidak tahu apakah itu perlu, tetapi jika Anda memasukkan baris: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); ke solusi Anda antara definisi fileList pertama dan definisi subDirs, ini akan mengembalikan jalur lengkap dan nama file untuk setiap file.
Doresoom
2
@ Doresoom: Saran yang bagus, meskipun saya memilih menggunakan FULLFILE, karena ini menangani pilihan pemisah file untuk Anda (yang berbeda pada UNIX dan Windows). Selain itu, Anda dapat melakukannya fileList = strcat(dirName,filesep,fileList);daripada menggunakan CELLFUN, meskipun Anda dapat berakhir dengan pemisah file ekstra yang tidak perlu dengan cara itu, yang juga ditangani oleh FULLFILE untuk Anda.
gnovice
2
@gnovice, @Doreseoom - Menurut mathworks.com/access/helpdesk/help/techdoc/ref/dir.html , urutan 'dir' yang dikembalikan bergantung pada OS. Saya tidak yakin apa yang terjadi jika, misalnya, Anda menyetel variabel DOS DIRCMD ke sesuatu yang mengubah urutan. Oktaf menanganinya dengan ok (. Dan .. masih pertama) tetapi saya tidak memiliki MATLAB untuk diuji.
mtrw
2
@gnovice: Ini di luar pertanyaan OP, tetapi saya merasa berguna untuk membangun ekspresi reguler ke dalam fungsi. 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 dan mengubah tanda tangan fungsi menjadi getAllFiles(dirName, pattern)(juga di baris ke-2 hingga terakhir)
Peter D
1
Jawaban bagus, terima kasih! Saya telah menguraikan kode untuk mendukung 2 parameter tambahan - stackoverflow.com/a/26449095/69555
Oz Radiano
25

Anda mencari dir untuk mengembalikan isi direktori.

Untuk mengulang hasil, Anda cukup melakukan hal berikut:

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

Ini akan memberi Anda keluaran dalam format berikut, misalnya:

name: 'my_file'
date: '01-Jan-2010 12:00:00'
bytes: 56
isdir: 0
datenum: []
James B
sumber
Dapatkah Anda membuatnya mencari secara rekursif termasuk file dalam subdirektori tetapi tidak termasuk direktori itu sendiri?
Gtker
Tidak berlebihan, tidak (saya tidak lagi memiliki akses reguler ke Matlab), tetapi ini dapat membantu Anda: mathworks.com/matlabcentral/fileexchange/…
James B
2
Bagaimana cara mengecualikan .dan ..?
Gtker
5
@ Runner: untuk mengecualikan. dan .., hapus dua entri pertama dalam output dir. Atau, jika Anda mencari jenis file tertentu, jalankan dir('*.ext'), yang secara otomatis mengecualikan direktori (kecuali jika diakhiri dengan .ext, tentu saja)
Jonas
14

Saya menggunakan kode yang disebutkan dalam jawaban hebat ini dan mengembangkannya untuk mendukung 2 parameter tambahan yang saya butuhkan dalam kasus saya. Parameternya adalah ekstensi file untuk difilter dan sebuah bendera yang menunjukkan apakah akan menggabungkan jalur lengkap ke nama file atau tidak.

Saya harap ini cukup jelas dan seseorang akan merasakan manfaatnya.

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

Contoh untuk menjalankan kode:

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

Anda dapat menggunakan regexp atau strcmp untuk menghilangkan .dan .. Atau Anda dapat menggunakan isdirfield jika Anda hanya ingin file dalam direktori, bukan folder.

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

atau gabungkan dua baris terakhir:

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

Untuk daftar folder di direktori tidak termasuk. dan ..

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

Dari titik ini, Anda harus bisa melempar kode ke loop for bersarang, dan terus mencari setiap subfolder sampai dirnames Anda mengembalikan sel kosong untuk setiap subdirektori.

Doresoom
sumber
@ Runner: Itu dilakukan jika Anda menggunakan beberapa for dan while loop ... tapi saya malas untuk mengimplementasikannya sekarang.
Doresoom
+1 meskipun tidak benar-benar menjawab pertanyaannya, ini memberikan cara untuk memilih direktori dengan cepat.
jhfrontz
7

Jawaban ini tidak langsung menjawab pertanyaan tetapi mungkin merupakan solusi yang baik di luar kotak.

Saya memberi suara positif pada solusi gnovice, tetapi ingin menawarkan solusi lain: Gunakan perintah yang bergantung pada sistem dari sistem operasi Anda:

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.

Positif:

  • Sangat cepat (dalam kasus saya untuk database 18.000 file di linux).
  • Anda dapat menggunakan solusi yang telah teruji dengan baik.
  • Anda tidak perlu mempelajari atau menemukan kembali sintaks baru untuk memilih *.wavfile ie .

Negatif:

  • Anda tidak independen dari sistem.
  • Anda mengandalkan satu string yang mungkin sulit diurai.
Lukas
sumber
3

Saya tidak tahu metode satu fungsi untuk ini, tetapi Anda hanya dapat menggunakan genpathdaftar subdirektori untuk mengulang . Daftar ini dikembalikan sebagai string direktori yang dipisahkan titik koma, jadi Anda harus memisahkannya menggunakan strread, yaitu

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

Jika Anda tidak ingin menyertakan direktori yang diberikan, hapus entri pertama dirlist, yaitu dirlist(1)=[];karena ini selalu merupakan entri pertama.

Kemudian dapatkan daftar file di setiap direktori dengan 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 mengembalikan pemisah direktori untuk platform yang menjalankan MATLAB.

Ini memberi Anda daftar nama file dengan jalur lengkap dalam daftar file array sel . Bukan solusi yang paling rapi, saya tahu.

JS Ng
sumber
Untuk alasan kinerja saya tidak mau genpath, itu pada dasarnya mencari dua kali.
Gtker
2
Satu kelemahan menggunakan GENPATH adalah ia hanya akan menyertakan subdirektori yang diperbolehkan di jalur MATLAB. Misalnya, jika Anda memiliki direktori yang diberi nama private, direktori tersebut tidak akan disertakan.
gnovice
1

Ini adalah fungsi praktis untuk mendapatkan nama file, dengan format yang ditentukan (biasanya .mat) di folder root!

    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

Dalam kasus Anda, Anda dapat menggunakan cuplikan berikut :)

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

Dengan sedikit modifikasi tetapi pendekatan yang hampir mirip untuk mendapatkan path file lengkap dari setiap sub folder

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
sumber