Edit multiple Matlab .m files using Matlab - matlab

I have some 50+ m files that worked in a previous driver version but are outdated for the newer driver version. As a result, I need to find and replace various variable or field names, and sometimes edit variable inputs for all these files.
For example, I'd like to find the line
src.aaaa = 100;
and replace it to:
src.bbbb = 100;
another example is to replace:
vid = videoinput('xxxx' ,1, 'yyy')
with:
vid = videoinput('kkkkkk' ,1, 'zzzz')
I've searched and found this discussion, that allows to search in multiple files, but not really edit or replace anything. I can handle matlab so I'm looking for a way to do that in matlab. Any ideas?

You could use the 'Find Files' dialog that you posted (Ctrl-Shift-F) to find each file you are looking for and then 'Find and Replace' (Ctrl+F) the specific lines you want to change.
As an example, find the file with src.aaaa = 100; using Ctrl+Shift+F. Then Ctrl+F and add the src.aaaa = 100; to the upper textbox and src.bbbb = 100; to the lower textbox.
From your post, it is unclear as to whether or not this would be feasible since I do not know how many different lines you would like to change in these m-files. How many are there? Are the m-files similar or are they all different?
If there are specific variables you are searching for, you could write a script to loop search through all the m-files using the dir function. Read the m-file into a string variable using fscanf. Then replace the variable in the string using strrep. And finally using fprintf to write to a new .m file with the corrected variables.
Refer to:
http://www.mathworks.com/help/matlab/ref/dir.html
http://www.mathworks.com/help/matlab/ref/fscanf.html
http://www.mathworks.com/help/matlab/ref/strrep.html
http://www.mathworks.com/help/matlab/ref/fprintf.html

A bit outside the box - but I would use the sed command - it does exactly what you want and is quick on it, but is you need to call it with system and build the command string. If you are on windows you may need to install it through msys or cygwin.

The m-File implementing Sekkou's suggestion:
clear all;
clc;
%% Parameter
directory = 'd:\xxx';
oldString = 'the old text';
newString = 'the new text';
regularExpression = '[\w]+\.m';
%% Determine files to manipulate
cd(directory)
allFilesInDirectory = dir;
%% Manipulieren der verweneten Dateien
disp('Manipulated Files:');
for idx = 1 : length(allFilesInDirectory)
if (~isempty ( regexp(allFilesInDirectory(idx).name, '[\w]+\.m','match') ))
disp(allFilesInDirectory(idx).name);
% Read and manipulate Text
fileIdRead = fopen(allFilesInDirectory(idx).name, 'r');
fileText = fscanf(fileIdRead,'%c');
fileTextNew = strrep(fileText, oldString, newString);
fclose(fileIdRead);
% Write Text
fileIdWrite = fopen(allFilesInDirectory(idx).name, 'w');
fprintf(fileIdWrite, '%c', fileTextNew);
fclose(fileIdWrite);
end
end

Ergodicity replied with some great code, but:
Some comments are in German rather than English
There is a general lack in commenting, which makes it hard to understand
I have attempted to fix these problems with the code below (I can't seem to get the code to display in MATLAB format very well using "language: lang-matlab", so paste it into MATLAB for easier reading):
close all;
clear all;
clc;
%% Parameters
% The directory in which to replace files. Currently this code does not modify files in
% sub-directories
directory = 'C:\Users\Name\Wonderful code folder';
% The string that will be replaced
oldString = sprintf('terrible mistake');
% The replacement string
newString = sprintf('all fixed now');
% The file name condition - what type of files will be examined
% It must contain any of the English character set (letters, numbers or underscore
% character i.e. a-zA-Z_0-9) and ends with a ".m" MATLAB extension (use \.txt for text files)
regularExpression = '[\w]+\.m';
%% Determine files to update, and update them as necessary
% Change the current directory to the user-specified one
cd(directory)
% Put the details of all files and folders in that current directory into a structure
allFilesInDirectory = dir;
% Initialise indexes for files that do and do not contain oldString
filesWithStringIndex = 1;
filesWithoutStringIndex = 1;
% For the number of files and folders in the directory
for idx = 1 : length(allFilesInDirectory)
% If the file name contains any of the English character set (letters, numbers or
% underscore character i.e. a-zA-Z_0-9) and ends with a ".m" filetype...
if (~isempty ( regexp(allFilesInDirectory(idx).name, '[\w]+\.m','match') ))
% Open the file for reading
fileIdRead = fopen(allFilesInDirectory(idx).name, 'r');
% Extract the text
fileText = fscanf(fileIdRead,'%c');
% Close the file
fclose(fileIdRead);
% Search for occurrences of oldString
occurrences = strfind(fileText,oldString);
% If an occurrence is found...
if ~isempty(occurrences)
% Replace any occurrences of oldString with newString
fileTextNew = strrep(fileText, oldString, newString);
% Open the file for writing
fileIdWrite = fopen(allFilesInDirectory(idx).name, 'w');
% Write the modified text
fprintf(fileIdWrite, '%c', fileTextNew);
% Close the file
fclose(fileIdWrite);
% Update the list of files that contained oldString
filesWithString{filesWithStringIndex} = allFilesInDirectory(idx).name;
% Update the index for files that contained oldString
filesWithStringIndex = filesWithStringIndex + 1;
else
% Update the list of files that did not contain oldString
filesWithoutString{filesWithoutStringIndex} = allFilesInDirectory(idx).name;
% Update the index for files that did not contain oldString
filesWithoutStringIndex = filesWithoutStringIndex + 1;
end
end
end
%% Display what files were changed, and what were not
% If the variable filesWithString exists in the workspace
if exist('filesWithString','var')
disp('Files that contained the target string that were updated:');
% Display their names
for i = 1:filesWithStringIndex-1, disp(filesWithString{i}); end
else
disp('No files contained the target string');
end
% Insert a clear line between lists
disp(' ');
% If the variable fileWithoutString exists in the workspace
if exist('filesWithoutString','var')
disp('Files that were not updated:');
% Display their names
for j = 1:filesWithoutStringIndex-1, disp(filesWithoutString{j}); end
else
disp('All files contained the target string.');
end

Related

Read a value from multiple text files and write all into another file

I have a list of sub-folders and each sub-folder has a text file name called simass.txt. From each of the simass.txt files I extract a c{1}{2,3} cell data (as done in the code below) and write it to a file name features.txt in sequential form in single column.
I am facing a problem where at the end I only have a single value in features.txt, which I believe is due to the values being overwritten. I'm supposed to have 1000 values in features.txt since I have 1000 sub-folders.
What am I doing wrong?
clc; % Clear the command window.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
% Define a starting folder wherever you want
start_path = fullfile(matlabroot, 'D:\Tools\Parameter Generation\');
% Ask user to confirm or change.
topLevelFolder = uigetdir(start_path);
if topLevelFolder == 0
return;
end
% Get list of all subfolders.
allSubFolders = genpath(topLevelFolder);
% Parse into a cell array.
remain = allSubFolders;
listOfFolderNames = {};
while true
[singleSubFolder, remain] = strtok(remain, ';');
if isempty(singleSubFolder)
break;
end
listOfFolderNames = [listOfFolderNames singleSubFolder];
end
numberOfFolders = length(listOfFolderNames)
% Process all text files in those folders.
for k = 1 : numberOfFolders
% Get this folder and print it out.
thisFolder = listOfFolderNames{k};
fprintf('Processing folder %s\n', thisFolder);
% Get filenames of all TXT files.
filePattern = sprintf('%s/simass.txt', thisFolder);
baseFileNames = dir(filePattern);
numberOfFiles = length(baseFileNames);
% Now we have a list of all text files in this folder.
if numberOfFiles >= 1
% Go through all those text files.
for f = 1 : numberOfFiles
fullFileName = fullfile(thisFolder, baseFileNames(f).name);
fileID=fopen(fullFileName);
c=textscan(fileID,'%s%s%s','Headerlines',10,'Collectoutput',true);
fclose(fileID);
%celldisp(c) % display all cell values
cellvalue=c{1}{2,3}
filePh = fopen('features.txt','w');
fprintf(filePh,cellvalue);
fclose(filePh);
fprintf(' Processing text file %s\n', fullFileName);
end
else
fprintf(' Folder %s has no text files in it.\n', thisFolder);
end
end
The problem is in the permission you use in fopen. From the documentation:
'w' - Open or create new file for writing. Discard existing contents, if any.
Which means you're discarding the contents every time, and you end up only having the last value. The fastest fix would be changing the permission to 'a', but I would suggest adding some changes to the code as follows:
Creating cellvalue before the loop, and read c{1}{2,3} into this new vector/cell array.
Perform the writing operation once, after cellvalue is fully populated.
cellvalue = cell(numberOfFiles,1);
for f = 1 : numberOfFiles
...
cellvalue{f} = c{1}{2,3};
end
fopen(...);
fprintf(...);
fclose(...);

How to import and save in Matlab Multiple Text Files creating a Matrix for each files

I have a very large data set which is divided in folders, I have 100 folders with approximately 200 text files each. I have been trying the for loop first of all importing one and then in another command importing the rest. But I am not interested in a dataarray but rather conserving each file with its name as I have to then match the dates among all the files and each file does not have the same amount of columns.
Each text file has is like the one I have attached, where the data I need is from the row 23 until column 13.
The data names are saves as 010010.txt, 010030.txt, 010050.txt ......until 014957.txt , they are not sequential
Apart from this I have created a script for importing one file but I would like to know how to repeat the same script for the rest.
filename = 'C:*\010010.txt';
startRow = 22;
formatSpec = '%4f%6f%6f%6f%6f%6f%6f%6f%6f%6f%6f%6f%6f%[^\n\r]';
fileID = fopen(filename,'r');
dataArray = textscan(fileID, formatSpec, 'Delimiter', '', 'WhiteSpace', '', 'HeaderLines' ,startRow-1, 'ReturnOnError', false);
fclose(fileID);
Untitled (010010) = [dataArray{1:end-1}];
I would like to repeat the same import process but for the rest files. I would appreciate any suggestion
The text files have the following format:
I only need from row 23 and column 13 and each txt file has different number of rows as some have data from 1992 - 2014 and other have only 2000 - 2014. The first column is the year and column 2 to 13 are months.
I guess you know the basepath under which all your folders are. You can then use something like this:
% First find all folders
folders = cell(0); % empty cell to save folder names
nFolders = 0;
allFolders = ls(basePath); % find all files and folders
for k=1:size(allFolders,1)
curFolder = fullfile(basePath,strtrim(allFolders(k,:)));
if isdir(curFolder) % find out if it is a folder
if ~(allFolders(k,1) == '.') % ignore '.' and '..'
folders{nFolders+1,1} = curFolder; % Save folder path
nFolders = nFolders + 1;
end
end
end
% Then find all files inside these folders
files = cell(0); % empty cell array for file names
nFiles = 0;
for k=1:nFolders % go through all folders
allFiles = ls(folders{k,1});
for l=1:size(allFiles,1) % go through all found files/subfolders
curFile = fullfile(folders{k},strtrim(allFiles(l,:)));
if ~isdir(curFile) % only select files
files{nFiles+1,1} = curFile; % and save it to the cell
nFiles = nFiles + 1;
end
end
end
Now you can iterate through the files cell and read all files according to your script. I see you are interested in the file name. You can extract the file name by
[path,filename,extension] = fileparts(files{k,1});
To import text files, you can use dlmread, which I think is more intuitive than textscan (but has more limitations, of course). For that you don't have to open the file using fopen, you can directly supply the file name.
value = dlmread(fileName,' ',[23,13,23,13]);
The delimiter is now a white space and only the value at row=23 / col=13 is read. Note that the range starts at row/col=0, not 1 like normally in Matlab - so maybe you'll have to change it to [22,12,22,12].

Loop through .txt files in a folder and search for certain characters in the file in MATLAB

How can I loop through .dbl and .txt files in a folder, find .txt files with a specific number and condition (e.g. 'laser on') and then do things to the associated .dbl file (if the names are similar)?
I don't really have much and I can't seem to access the file names I want to look through using getfield(files, 'name') so I'm really stuck. Here is what I have so far so as to give some more structure to my question.
% specify folder with the load function to manipulate .dbl files
folder = 'some folder';
% specify folder that has the data
folder2 = 'some other folder';
cd(folder);
addpath(folder2);
% specify parameters implemented in data collection program
start_delay = 0; % in ps
step_size = 20; % in ps
n_steps = 30;
% loop through folders
files = dir(folder2);
for i = 1:size(files,1)
if i == '*.txt
% find string 'ON'
% find a number in .txt file
% for .txt files with string 'ON', look for .txt files for delay =0, then 20, then 40, etc.
% find associated .dbl file
% manipulate .dbl file
end
end
The things you are looking for are the *.xxx comand for dir and strfind, take a look at this example:
txtList=dir('*.txt');
sblList=dir('*.dbl');
for ii=1:length(txtList)
fid=fopen(txtList(ii).name);
C= textscan(fid,'%s'); %depends on your formating
C=C{1}{1}; %supposing you .txt is really just one string
fclose(fid);
if (sum(strfind(C,'ON'))) %for .txt files with string 'ON'...
Equals0=strfind(C,'0'); % ... look for =0,...
Equals20=strfind(C,'20'); %then =20
%... etc
end
%you get the idea...
%do whatever you want with dblList
end

Read through and save files with different filenames

I have a list of CSV files. The filenames of these files have been stored in the form [year '_MDA8_mat.dat']. I want to read in each of these files into MATLAB and save the output. How can I write the code so that each year is considered in turn and the output .mat file will be saved for each year?
Here's what I have for reading in one of the files:
flist = fopen('2006_MDA8_mat.dat'); % Open the list of file names - CSV files of states with data under consideration
nt = 0; % Counter will go up one for each file loaded
while ~feof(flist) % While end of file has not been reached
for i = 1:27299 % Number of files
fname = fgetl(flist); % Reads next line of list, which is the name of the next data file
disp(fname); % Stores name as string in fname
nt = nt+1; % Time index
load (fname, 'site_data'); % Load current file. It is all the data for one site for one year
O3_data{i} = site_data;
% Do some more stuff
end
save ('2006_MDA8_1990_2014.mat', '-v7.3')
I tried to write a for loop like this:
year = 2006:2014
for y = 1:9
flist = fopen([year(y) '_MDA8_mat.dat']);
nt = 0; % Counter will go up one for each file loaded
while ~feof(flist) % While end of file has not been reached
for i = 1:1500 % Number of files
% Same as above
end
end
save ([year '_MDA8_1990_2014.mat'], '-v7.3')
end
However, when I run this, it doesn't do the same thing as it did for the one file script. I'm not quite sure where the error occurs, but MATLAB tells me there's an error with feof, which doesn't seem to make sense.
When combining numbers and strings, you need to do a num2str on the number:
[num2str(year) '_MDA8_1990_2014.mat']

How to read numbered sequence of .dat files into MATLAB

I am trying to load a numbered sequence of ".dat" named in the form a01.dat, a02.dat... a51.dat into MATLAB. I used the eval() function with the code below.
%% To load each ".dat" file for the 51 attributes to an array.
a = dir('*.dat');
for i = 1:length(a)
eval(['load ' a(i).name ' -ascii']);
end
attributes = length(a);
I ran into problems with that as I could not easily manipulate the data loaded with the eval function. And I found out the community is strongly against using eval. I used the csvread() with the code below.
% Scan folder for number of ".dat" files
datfiles = dir('*.dat');
% Count Number of ".dat" files
numfiles = length(datfiles);
% Read files in to MATLAB
for i = 1:1:numfiles
A{i} = csvread(datfiles(i).name);
end
The csvread() works for me but it reads the files but messes up the order when it reads the files. It reads a01.dat first and then a10.dat and a11.dat and so on instead of a01.dat, a02.dat... The contents of each files are signed numbers. Some are comma-delimited and single column and this is an even split. So a01.dat's contents are comma-delimited and a02.dat's content are in a single column.
Please how do I handle this?
Your problem seems to be sorting of the files. Drawing on a question on mathworks, this should help you:
datfiles = dir('*.mat');
name = {datfiles.name};
[~, index] = sort(name);
name = name(index);
And then you can loop with just name:
% Read files in to MATLAB
for i = 1:1:numfiles
A{i} = csvread(name{i});
end