【问题标题】:How do I sort files into multiple folders in MATLAB?如何在 MATLAB 中将文件分类到多个文件夹中?
【发布时间】:2009-12-08 02:32:38
【问题描述】:

我有点卡在一个问题上。我每天都会生成大量文件,我需要按文件名和日期对它们进行排序。我需要这样做,以便我的 MATLAB 脚本可以读取它们。我目前手动执行此操作,但想知道 MATLAB 中是否有更简单的方法来排序和复制文件。

我的文件名如下:

data1_2009_12_12_9.10
data1_2009_12_12_9.20
data1_2009_12_12_9.30
data1_2009_12_12_9.40
data2_2009_12_12_9.10
data2_2009_12_12_9.20
data2_2009_12_12_9.30
data2_2009_12_12_9.40
data3_2009_12_12_9.10
data3_2009_12_12_9.20
data3_2009_12_12_9.30
data3_2009_12_12_9.40
...

还有大量这样的文件。

以上问题的补充:

必须有一种更简单的方法将文件拼接在一起。 我的意思是复制文件 文件“data1_2009_12_12_9.10”之后的“data1_2009_12_12_9.20”等等,... 这样我就剩下一个名为 data1_2009_12_12 的巨大 txt 文件(或任何其他文件)。包含拼接在一起的所有数据。 现在我知道的唯一方法是在matlab中使用单独的dlmread命令打开所有文件,然后xls一个接一个地写入(或者更简单的手动复制粘贴方式)

【问题讨论】:

  • 所有这些文件都在一个文件夹中吗?另外,您的意思是在您的示例中重复文件名,还是最后一个数字应该每增加 10?
  • 是的,所有文件一开始都在同一个文件夹中。文件名不重复。第一行在文件名中有不同的时间(文件名的一部分)。 data19.10, data19.20第二行有data3****
  • 那么,您到底想要什么结果呢?您的输入文件已经命名,因此它们按字母顺序按数据集排序,然后按时间排序,对吗? (所有按时间排序的 data1,按时间排序的所有 data2,等等。)如果你在 Unix 系统上,matlab 的 system() 函数可以运行一个 shell 命令,它可能类似于 'mkdir data1; mv -t data1 data1_*'。 (我在 GNU/Linux 上有 octave,但我用得不多,所以我不知道如何在 octave 中使用它的 ls、排序和重命名函数来执行此操作......)
  • @AP:我根据我的认为你的意思修改了你问题中一些文件名的最后两位数字(其中很多都有@987654322 @当我猜他们应该是2030,等等)。
  • 关于您的编辑...您正在使用哪种机器(Windows、Linux 等)?您可以使用系统命令更轻松地连接数据文件。

标签: matlab file-io directory


【解决方案1】:

在功能成像研究领域工作时,我经常不得不将大量文件按特定顺序分类以进行处理。下面是一个示例,说明如何查找文件、解析某些标识符字符串的文件名,然后按给定条件对文件名进行排序...

正在收集文件...

您可以先使用DIR 函数从您的目录中获取所有文件名的列表:

dirData = dir('your_directory');      %# Get directory contents
dirData = dirData(~[dirData.isdir]);  %# Use only the file data
fileNames = {dirData.name};           %# Get file names

用正则表达式解析文件名...

您的文件名似乎具有以下格式:

'data(an integer)_(a date)_(a time)'

所以我们可以使用REGEXP 来解析与上述格式匹配的文件名,并提取data 后面的整数、日期的三个值和时间的两个值。因此,用于匹配的表达式将为每个有效文件名捕获 6 个"tokens"

expr = '^data(\d+)\_(\d+)\_(\d+)\_(\d+)\_(\d+)\.(\d+)$';
fileData = regexp(fileNames,expr,'tokens');  %# Find tokens
index = ~cellfun('isempty',fileData);        %# Find index of matches
fileData = [fileData{index}];                %# Remove non-matches
fileData = vertcat(fileData{:});             %# Format token data
fileNames = fileNames(index);                %# Remove non-matching file names

根据标记排序...

您可以将上述字符串标记转换为数字(使用STR2DOUBLE 函数),然后将日期和时间值转换为日期数字(使用函数DATENUM):

nFiles = size(fileData,1);              %# Number of files matching format
fileData = str2double(fileData);        %# Convert from strings to numbers
fileData = [fileData zeros(nFiles,1)];  %# Add a zero column (for the seconds)
fileData = [fileData(:,1) datenum(fileData(:,2:end))];  %# Format dates

变量fileData 现在将是一个nFiles-by-2 数值矩阵。您可以使用函数SORTROWS 对这些值进行排序。以下代码将首先按单词data 后面的整数排序,然后按日期编号:

[fileData,index] = sortrows(fileData,1:2);  %# Sort numeric values
fileNames = fileNames(index);               %# Apply sort to file names

连接文件...

fileNames 变量现在包含给定目录中与所需文件名格式匹配的所有文件的元胞数组,首先按单词 data 后面的整数排序,然后按日期排序。如果您现在想将所有这些文件连接成一个大文件,您可以尝试使用SYSTEM 函数调用系统命令来为您执行此操作。如果您使用的是 Windows 机器,您可以执行我在 this answer to another SO question 中描述的操作,其中我展示了如何使用 DOS for commandconcatenate text files。您可以尝试以下方法:

inFiles = strcat({'"'},fileNames,{'", '});  %# Add quotes, commas, and spaces
inFiles = [inFiles{:}];                     %# Create a single string
inFiles = inFiles(1:end-2);                 %# Remove last comma and space
outFile = 'total_data.txt';                 %# Output file name
system(['for %f in (' inFiles ') do type "%f" >> "' outFile '"']);

这应该创建一个文件total_data.txt,其中包含来自各个文件的所有数据,这些数据按照它们的名称出现在变量fileNames 中的顺序连接起来。请记住,每个文件可能都必须以换行符结尾才能正确连接。

【讨论】:

  • 哇,代码看起来很复杂。下班后我会试着解读这个。谢谢
  • 非常感谢,如果文件太大,我必须将其合并到我的程序中,以便我可以在我的程序中处理更多内容。
  • 我了解上述内容是否比您需要的更复杂。实际上,我是根据我用来收集文件和目录的一些代码改编它的,这些文件和目录具有更多样化和更复杂的命名约定集。 ;)
【解决方案2】:

@gnovice 建议的替代方法是遍历文件名并使用 sscanf() 恢复您感兴趣的文件名中的不同部分:

n = sscanf(filename, 'data%d_%d_%d_%d_%d.%d')
n(1)    %# data number
n(2)    %# the year
...

示例:

files = dir('data*');                 %# list all entries beginning with 'data'
parts = zeros(length(files), 6);      %# read all the 6 parts into this matrix
for i=1:length(files)
    parts(i,:) = sscanf(files(i).name, 'data%d_%d_%d_%d_%d.%d')';  %'#transposed
end

[parts idx] = sortrows(parts, [6 1]); %# sort by one/multiple columns of choice
files = files(idx);                   %# apply the new order to the files struct

编辑:

我刚刚看到您关于合并这些文件的编辑。这可以从外壳轻松完成。例如,让我们为 2009 年的所有数据创建一个大文件(假设将文件堆叠在一起是有意义的):

在 Windows 上:

type data*_2009_* > 2009.backup

在 Unix 上:

cat data*_2009_* > 2009.backup

【讨论】:

  • 您的答案的第一部分效果很好,并且比使用 REGEXP 更清晰、更容易理解;),但如果目录中有其他不相关的文件名称可能会遇到问题像“data10.txt”。我认为 shell 命令的第二部分只有在目录中文件的默认顺序已经适当排序的情况下才有效,可能不是对于 OP 正在执行的操作(即“data1_2009_12_12_9 .10" 将在 "data1_2009_12_9_9.10" 之前以字母数字形式出现)。
  • 重点是展示如何使用 shell 连接文件。我们总是可以插入从上一步排序的文件名,并使用 MATLAB 的 system() 函数发出命令,甚至可以使用 cat datafile >> output 一次一个文件附加到输出文件(在类似于之前的 for 循环)。至于第一点,您可以使搜索模式更具体,例如data*_*_*_*_*.*,以避免任何不相关的文件:)
  • @Amro.. 拼接文件的绝妙技巧。我从来不知道有人可以在命令提示符中做到这一点..
【解决方案3】:

在 Matlab 中的函数调用

files = dir('.');

返回带有字段的结构(称为文件)

name

date

bytes

isdir

datenum

您可以使用常用的 Matlab 技术来处理文件名。

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    • 2015-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多