我很少遇到问题。我每天都会生成大量文件,我需要按文件名和日期对它们进行排序。我需要这样做,所以我的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逐个写入(或者手动复制粘贴的更简单的方法)
答案 0 :(得分:6)
在功能成像研究领域工作,我经常不得不将大量文件分类为特定的处理顺序。下面是一个如何查找文件,解析某些标识符字符串的文件名,然后按给定标准对文件名进行排序的示例...
您可以使用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
- 乘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 command到concatenate 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
中的顺序连接在一起。请记住,每个文件可能都必须以换行符结束才能正确连接。
答案 1 :(得分:3)
@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
我刚看到你关于合并这些文件的编辑。这可以通过shell轻松完成。例如,让我们为2009年的所有数据创建一个大文件(假设将文件堆叠在彼此之上是有意义的):
Windows上的type data*_2009_* > 2009.backup
Unix上的cat data*_2009_* > 2009.backup
答案 2 :(得分:1)
在Matlab函数调用
files = dir('.');
返回带有字段
的结构(称为文件)name
date
bytes
isdir
datenum
您可以使用常用的Matlab技术来操作files.names。