MATLAB: How to decide the next problem

renamestrread

I want to rename files in a directory. I have a cell variable named fileList after using this script:
function fileList = getAllFiles(dirName)
dirData = dir(dirName);
dirIndex = [dirData.isdir];
fileList = {dirData(~dirIndex).name}';';
if ~isempty(fileList)
fileList = cellfun(@(x) fullfile(dirName,x),...
fileList,'UniformOutput',false);
end
subDirs = {dirData(dirIndex).name};
validIndex = ~ismember(subDirs,{'.','..'});
for iDir = find(validIndex)
nextDir = fullfile(dirName,subDirs{iDir});
fileList = [fileList; getAllFiles(nextDir)];
end
end;
Files` names are: D:\20140210_test\Experiment1\ExpData_1_1.exp
I need files` names such as: 20140210.test.ExpData_1_1.exp
But I have problem with function strread. When I type:
FilesNames=[];
for i=1:length(fileList)
for j=1:7
FilesNames(i,j)=strread('fileList{i,1}', '%s %s %s %s %s %s %s', 'delimiter', '\\');
end
end
the error is:
Error using dataread Number of outputs must match the number of unskipped input fields.
Error in strread (line 51) [varargout{1:nlhs}]=dataread('string',varargin{:});
What can I do to avoid this one?

Best Answer

Elina - the error message is telling you that you are not providing enough output variables given the input fields. Looking at strread, [A, B, ...] = strread('str', 'format') reads data from str into variables A, B, and so on using the specified format. The number of output variables A, B, etc. must be equal to the number of format specifiers (e.g., %s or %d) in the format argument. Since you are providing seven format specifiers, then you must have seven output variables. And I think that you know this based on your code where you have the inner loop iterate from 1 to 7. But this won't work the way you have intended because you are only using one output variable, FilesNames(i,j) at each iteration. You might have more success if you were to declare FilesNames as a cell array
FilesNames=cell(length(fileList),7);
for k=1:length(fileList)
[FilesNames{k,:}]=strread(fileList{k,1}, '%s %s %s %s %s %s %s', 'delimiter', '\\');
end
Note how I've removed the quotes around the first input to strread. If we leave the quotes, then each iteration will pass the same string of 'fileList{k,1}', rather than the file name accessed at fileList{k,1}.
The above may work provided that a file is no more than six folders deep from the root directory. (If seven or more, then the cell arrays in stored in FilesNames double up. Check the following example
% file is six folders deep from Users
fileName = '/Users/geoff/Development/bitbucket_repos/matlab/testing/2014-09-30_110331.mat';
[FilesNames{1,:}]=strread(fileName, '%s %s %s %s %s %s %s', 'delimiter', '/');
then the first element of FilesNames is a 2x1 column vector
FilesNames{1}
ans =
''
'2014-09-30_110331.mat'
Why not try something else? Suppose your file name and path is
fileAndPath = 'D:\20140210_test\Experiment1\ExpData_1_1.exp';
Then we can use fileparts to get the path, filename, and extension
[path,filename,ext] = fileparts(fileAndPath);
Now if we are looking for the numeric portion of path that is followed by '_test' then we could use regexp to get us that data
destFilename = strrep(char(regexp(path,'[0-9]+_test','match')),'_','.');
In the above, we use the expression '[0-9]+_test' to match in path where there is at least one (+) numeric character ([0-9]) that is followed by '_test'. We then replace the underscore with a period using strrep.
We then create the new file name with the file parts that we have already extracted
destFilename = [destFilename '.' filename ext];
which yields
destFilename =
20140210.test.ExpData_1_1.exp
Your code would be something like the following then
newFilenames=cell(length(fileList),1);
for k=1:length(fileList)
fileAndPath = fileList{k};
[path,filename,ext] = fileparts(fileAndPath);
destFilename = strrep(char(regexp(path,'[0-9]+_test','match')),'_','.');
newFilenames{k} = [destFilename '.' filename ext];
end