จะรับไฟล์ทั้งหมดภายใต้ไดเร็กทอรีเฉพาะใน MATLAB ได้อย่างไร?


102

ฉันต้องการรับไฟล์เหล่านั้นทั้งหมดไว้ข้างใต้D:\dicและวนซ้ำเพื่อประมวลผลทีละไฟล์

MATLAB รองรับการทำงานประเภทนี้หรือไม่?

สามารถทำได้ในสคริปต์อื่น ๆ เช่น PHP, Python ...

คำตอบ:


130

อัปเดต:เนื่องจากโพสต์นี้ค่อนข้างเก่าและฉันได้แก้ไขยูทิลิตี้นี้เป็นจำนวนมากสำหรับการใช้งานของฉันเองในช่วงเวลานั้นฉันคิดว่าฉันควรโพสต์เวอร์ชันใหม่ รหัสใหม่ล่าสุดของฉันสามารถพบได้บนMathWorks ไฟล์แลกเปลี่ยนdirPlus.m : นอกจากนี้คุณยังจะได้รับแหล่งที่มาจากGitHub

ฉันได้ทำการปรับปรุงหลายอย่าง ตอนนี้มีตัวเลือกให้คุณนำหน้าเส้นทางแบบเต็มหรือส่งคืนเฉพาะชื่อไฟล์ (รวมจากDoresoomและOz Radiano ) และใช้รูปแบบนิพจน์ทั่วไปกับชื่อไฟล์ (รวมจากPeter D ) นอกจากนี้ฉันได้เพิ่มความสามารถในการใช้ฟังก์ชันการตรวจสอบความถูกต้องกับแต่ละไฟล์ทำให้คุณสามารถเลือกได้ตามเกณฑ์อื่น ๆ ที่ไม่ใช่แค่ชื่อ (เช่นขนาดไฟล์เนื้อหาวันที่สร้าง ฯลฯ )


หมายเหตุ:ใน MATLAB เวอร์ชันใหม่กว่า (R2016b และใหม่กว่า) dirฟังก์ชันนี้มีความสามารถในการค้นหาแบบวนซ้ำ! คุณสามารถทำสิ่งนี้เพื่อรับรายชื่อ*.mไฟล์ทั้งหมดในโฟลเดอร์ย่อยทั้งหมดของโฟลเดอร์ปัจจุบัน:

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

รหัสเก่า: (สำหรับลูกหลาน)

นี่คือฟังก์ชันที่ค้นหาซ้ำผ่านไดเรกทอรีย่อยทั้งหมดของไดเร็กทอรีที่กำหนดโดยรวบรวมรายชื่อไฟล์ทั้งหมดที่พบ:

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

หลังจากบันทึกฟังก์ชันข้างต้นไว้ที่ใดที่หนึ่งบนเส้นทาง MATLAB ของคุณแล้วคุณสามารถเรียกใช้ฟังก์ชันดังต่อไปนี้:

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

3
+1 - ทางออกที่ยอดเยี่ยม ฉันไม่รู้ว่ามันจำเป็นหรือเปล่า แต่ถ้าคุณใส่บรรทัด: fileList = cellfun (@ (x) strcat ([dirName, '\'], x), fileList, 'UniformOutput', 0); ในโซลูชันของคุณระหว่างนิยาม fileList แรกและนิยาม subDirs มันจะส่งคืนพา ธ เต็มและชื่อไฟล์สำหรับแต่ละไฟล์
Doresoom

2
@Doresoom: ข้อเสนอแนะที่ดีแม้ว่าฉันจะใช้ FULLFILE แทนเนื่องจากมันจัดการตัวเลือกของตัวคั่นไฟล์สำหรับคุณ (ซึ่งแตกต่างกันใน UNIX และ Windows) นอกจากนี้คุณสามารถทำได้fileList = strcat(dirName,filesep,fileList);แทนที่จะใช้ CELLFUN แม้ว่าคุณจะสามารถใช้ตัวคั่นไฟล์พิเศษที่ไม่จำเป็นได้ด้วยวิธีนี้ซึ่ง FULLFILE ก็ดูแลคุณเช่นกัน
gnovice

2
@gnovice, @Doreseoom - อ้างอิงจากmathworks.com/access/helpdesk/help/techdoc/ref/dir.htmlลำดับที่ 'dir' ส่งคืนจะขึ้นอยู่กับระบบปฏิบัติการ ฉันไม่แน่ใจว่าจะเกิดอะไรขึ้นเช่นหากคุณตั้งค่าตัวแปร DOS DIRCMD เป็นสิ่งที่เปลี่ยนลำดับ Octave จัดการได้โอเค (. และ .. ยังเป็นที่หนึ่ง) แต่ฉันไม่มี MATLAB ให้ทดสอบ
mtrw

2
@gnovice: นี่อยู่นอกเหนือคำถามของ OP แต่ฉันพบว่ามีประโยชน์ในการสร้างนิพจน์ทั่วไปลงในฟังก์ชัน 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 และเปลี่ยนลายเซ็นฟังก์ชันเป็นgetAllFiles(dirName, pattern)(เช่นในบรรทัดที่ 2 ถึงบรรทัดสุดท้าย)
Peter D

1
คำตอบที่ดีขอบคุณ! ฉันได้อธิบายโค้ดอย่างละเอียดเพื่อรองรับพารามิเตอร์เพิ่มเติม 2 ตัว - stackoverflow.com/a/26449095/69555
Oz Radiano

25

คุณกำลังมองหาdirเพื่อส่งคืนเนื้อหาไดเร็กทอรี

หากต้องการวนซ้ำผลลัพธ์คุณสามารถทำสิ่งต่อไปนี้:

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

สิ่งนี้ควรให้ผลลัพธ์ในรูปแบบต่อไปนี้เช่น:

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

คุณสามารถทำการค้นหาซ้ำรวมถึงไฟล์ในไดเรกทอรีย่อย แต่ไม่รวมไดเร็กทอรีได้หรือไม่?
Gtker

ไม่ได้อยู่เหนือศีรษะของฉันไม่ (ฉันไม่สามารถเข้าถึง Matlab ได้อีกต่อไป) แต่สิ่งนี้อาจช่วยคุณได้: mathworks.com/matlabcentral/fileexchange/…
James B

2
วิธีการแยก.และ..?
Gtker

5
@Runner: เพื่อไม่รวม และ .. ลบสองรายการแรกในเอาต์พุตของ dir หรือในกรณีที่คุณกำลังมองหาไฟล์ประเภทใดประเภทหนึ่งให้เรียกใช้dir('*.ext')ซึ่งจะไม่รวมไดเรกทอรีโดยอัตโนมัติ (เว้นแต่ว่าจะลงท้ายด้วย. ถัดไป)
Jonas

14

ฉันใช้รหัสที่กล่าวถึงในคำตอบที่ยอดเยี่ยมนี้และขยายเพื่อรองรับพารามิเตอร์เพิ่มเติม 2 ตัวที่ฉันต้องการในกรณีของฉัน พารามิเตอร์คือนามสกุลไฟล์ที่ใช้กรองและแฟล็กที่ระบุว่าจะต่อพา ธ แบบเต็มเข้ากับชื่อไฟล์หรือไม่

ฉันหวังว่ามันจะชัดเจนพอและใครบางคนจะพบว่ามันเป็นประโยชน์

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

ตัวอย่างการรันโค้ด:

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

8

คุณสามารถใช้ regexp หรือ strcmp เพื่อกำจัด.และ.. หรือคุณสามารถใช้isdirฟิลด์นี้หากคุณต้องการเฉพาะไฟล์ในไดเร็กทอรีไม่ใช่โฟลเดอร์

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

หรือรวมสองบรรทัดสุดท้าย:

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

สำหรับรายการโฟลเดอร์ในไดเร็กทอรีไม่รวม และ ..

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

จากจุดนี้คุณควรจะสามารถโยนรหัสในการวนซ้ำที่ซ้อนกันและค้นหาแต่ละโฟลเดอร์ย่อยต่อไปจนกว่าชื่อของคุณจะส่งคืนเซลล์ว่างสำหรับแต่ละไดเร็กทอรีย่อย


@Runner: ถ้าคุณใช้บางส่วนในขณะที่ลูป ... แต่ฉันขี้เกียจที่จะใช้ตอนนี้
Doresoom

+1 แม้ว่าจะไม่ได้ตอบคำถามอย่างตรงไปตรงมา แต่ก็มีวิธีการคัดแยกไดเรกทอรีออกอย่างรวดเร็ว
jhfrontz

7

คำตอบนี้ไม่ได้ตอบคำถามโดยตรง แต่อาจเป็นทางออกที่ดีนอกกรอบ

ฉันยกระดับโซลูชันของ gnovice แต่ต้องการเสนอโซลูชันอื่น: ใช้คำสั่งที่ขึ้นกับระบบของระบบปฏิบัติการของคุณ:

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.

บวก:

  • เร็วมาก (ในกรณีของฉันสำหรับฐานข้อมูล 18000 ไฟล์บน linux)
  • คุณสามารถใช้โซลูชันที่ผ่านการทดสอบอย่างดี
  • คุณไม่จำเป็นต้องเรียนรู้หรือสร้างไวยากรณ์ใหม่เพื่อเลือก*.wavไฟล์ie

เชิงลบ:

  • คุณไม่ได้เป็นอิสระจากระบบ
  • คุณต้องใช้สตริงเดี่ยวซึ่งอาจแยกวิเคราะห์ได้ยาก

3

ผมไม่ทราบว่าเป็นวิธีการเดียวฟังก์ชั่นนี้ แต่คุณสามารถใช้genpathเพื่อ recurse รายการไดเรกทอรีย่อยเท่านั้น รายการนี้จะส่งคืนเป็นสตริงของไดเร็กทอรีที่คั่นด้วยอัฒภาคดังนั้นคุณจะต้องแยกรายการโดยใช้ strread เช่น

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

หากคุณไม่ต้องการรวมไดเร็กทอรีที่กำหนดให้ลบรายการแรกของdirlistนั่นคือdirlist(1)=[];เนื่องจากเป็นรายการแรกเสมอ

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 ทำงานอยู่

นี้จะช่วยให้คุณรายการของชื่อไฟล์ที่มีเส้นทางเต็มรูปแบบในเซลล์อาร์เรย์filenamelist ไม่ใช่วิธีแก้ปัญหาที่สะอาดที่สุดฉันรู้


ด้วยเหตุผลด้านประสิทธิภาพที่ฉันไม่ต้องการgenpathมันจะค้นหาสองครั้งเป็นหลัก
Gtker

2
ข้อเสียเปรียบอย่างหนึ่งในการใช้ GENPATH คือจะรวมเฉพาะไดเรกทอรีย่อยที่อนุญาตบนเส้นทาง MATLAB ตัวอย่างเช่นหากคุณมีชื่อไดเรกทอรีprivateจะไม่ถูกรวมไว้
gnovice

1

นี่เป็นฟังก์ชันที่มีประโยชน์สำหรับการรับชื่อไฟล์โดยมีรูปแบบที่ระบุ (โดยปกติ.mat) ในโฟลเดอร์รูท!

    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

ในกรณีของคุณคุณสามารถใช้ตัวอย่างต่อไปนี้ :)

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

0

ด้วยการปรับเปลี่ยนเพียงเล็กน้อย แต่เกือบจะคล้ายกันเพื่อให้ได้เส้นทางไฟล์แบบเต็มของแต่ละโฟลเดอร์ย่อย

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  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.