How to rename a lot of mfiles in a folder

4 views (last 30 days)
Hello,
I have a folder which contains many mfiles. I would like to change the name of these mfiles in
a for-loop (they are too many of them). I did google it and studied similar questions but I do not understand why
it does not work for me. To make things easy assume that I have a folder called D:\something which contains 4
mfiles m1.m, m2.m, u1.m,u2.m and only those which start with 'm' should change into capital M. So, at the end
I should get M1.m,M2.m,u1.m,u2.m . As you know the name of mfiles and the corresponding function name when we open it should be the same. So, this is the part I am not confident to do. So, I am not simpley asking something like "how to change 2 PDF files A1.pdf,A2.pdf
into, say, B1.pdf,B2.pdf ".
I have seen in google that people use the command 'dir' and then loop over the file names and if a particular file name should be
changed they use the command 'movefile'. To be honest, I get stocked in the begining. The answer to my question should be like the following:
files = dir('D:\something');
for i=1:length(files)
[~, NAME,~] = fileparts(files(id).name);
...
use 'movefiles'
end
I do not understand why when I, for instance, type [~, NAME,~] = fileparts(files(1).name) then I get
1×0 empty char array
I have no idea why it is like this (I hate it) !!!
Any idea?
Thanks
Babak
  6 Comments
Image Analyst
Image Analyst on 4 Dec 2022
Edited: Image Analyst on 4 Dec 2022
MATLAB does have a command to rename files. It's called movefile
You did not answer Jan. Do you just want to capitalize the first letter, or all the letters of the filename?
And not all m-files have or need a function definition line so you should just put one in if you have a function, but if you have a script, you don't need it. MATLAB cannot know your intent regarding this -- theirre Mind Reading Toolbox is still under development.
Mohammad Shojaei Arani
Mohammad Shojaei Arani on 4 Dec 2022
Yes, just capitalize one letter or maximum the first two letters (I promise that I do not go beyound this).

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 4 Dec 2022
Try this:
folder = pwd; % or 'D:\something'
filePattern = fullfile(folder, '*.*'); % or '*.m' if you want only m-files.
fileList = dir(filePattern)
% Remove folders.
fileList([fileList.isdir]) = []
% Get all file names
allBaseFileNames = {fileList.name};
for k = 1 : numel(allBaseFileNames)
thisName = allBaseFileNames{k};
sourceFullFileName = fullfile(folder, thisName);
% Capitalize the first letter
thisName(1) = upper(thisName(1));
destinationFullFileName = fullfile(folder, thisName);
fprintf('Renaming %s to "%s".\n', sourceFullFileName, destinationFullFileName);
% Do the renaming: (Comment out to test without doing the actual renaming)
movefile(sourceFullFileName, destinationFullFileName);
end
  2 Comments
Mohammad Shojaei Arani
Mohammad Shojaei Arani on 5 Dec 2022
Hi,
Thanks you VERY much for your VERY kind response. I appreciate it greatly!
I think you have solved my problem. I just got the following error
matlab Error using movefile Cannot copy or move a file or directory onto itself.
to fix it I created another folder as destination and it modifies the files in the destination folder. I
do not mind about this too much.
Also, your code just changes the mfile names but it does not check whether the function name and file name match. However, apparently mtlab does not care about this (I mean, for instance, that when I want to calculate something like M1(1,2) where tthe mfile is called M1.m but the function name is m1.m then fourtunately I can still type the command M1(1,2) and fourtunately MATLAB does not care about this).
Thanks again!
Babak
Image Analyst
Image Analyst on 5 Dec 2022
If the first letter is already capitalized, then the source and destination file names are identical and it will throw an error so you need to skip the file if it's already in the proper format and does not need to be changed:
folder = pwd; % or 'D:\something'
filePattern = fullfile(folder, '*.*'); % or '*.m' if you want only m-files.
fileList = dir(filePattern)
% Remove folders.
fileList([fileList.isdir]) = []
% Get all file names
allBaseFileNames = {fileList.name};
for k = 1 : numel(allBaseFileNames)
thisName = allBaseFileNames{k};
sourceFullFileName = fullfile(folder, thisName);
% Capitalize the first letter
thisName(1) = upper(thisName(1));
destinationFullFileName = fullfile(folder, thisName);
if strcmp(destinationFullFileName, sourceFullFileName)
continue; % Skip this file if there is no change to the name.
end
fprintf('Renaming %s to "%s".\n', sourceFullFileName, destinationFullFileName);
% Do the renaming: (Comment out to test without doing the actual renaming)
movefile(sourceFullFileName, destinationFullFileName);
end
Here is a start at checking the function name inside the file. This is just for one single file so you should make it into a function and call it from inside the loop of the code above. I'm sure you'll be able to finish it.
% Open the file for reading in text mode.
fileID = fopen(fullFileName, 'rt');
% Read the first line of the file.
textLine = fgetl(fileID);
lineCounter = 1;
while ischar(textLine)
% Print out what line we're operating on.
fprintf('%s\n', textLine);
% See if the line contains both "function" and the basefilename.
[f, baseFileNameNoExt, ext] = fileparts(fullFileName)
if contains(textLine, 'function') && contains(textLine, baseFileNameNoExt, "IgnoreCase",true)
index = strfind(lower(textLine), lower(baseFileNameNoExt))
numChars = length(baseFileNameNoExt);
functionNameInFile = textLine(index : (index + numChars - 1));
if ~strcmp(fullFileName, baseFileNameNoExt)
% Function name in file does not match the name from the operating system.
% For example the capitalization may not match.
% Replace text line with fixed one using strrep. Then you'll have to create a
% temporary output file to write back out the fixed one.
% Then delete the original one and use movefile to rename the
% temporary file to the original filename.
end
end
% Read the next line.
textLine = fgetl(fileID);
lineCounter = lineCounter + 1;
end
% All done reading all lines, so close the file.
fclose(fileID);

Sign in to comment.

More Answers (2)

Steven Lord
Steven Lord on 4 Dec 2022
Let's look at a simple example of what's in the temporary directory.
D = dir(tempdir)
D = 10×1 struct array with fields:
name folder date bytes isdir datenum
What's the first file (or "file") in that list?
D(1)
ans = struct with fields:
name: '.' folder: '/tmp' date: '04-Dec-2022 15:02:06' bytes: 0 isdir: 1 datenum: 7.3886e+05
This "file" refers to the current directory. There's at least one other file like this in your directory, and given what's in this directory it's the second "file". [These are not always the first and second file in the directory.]
D(2)
ans = struct with fields:
name: '..' folder: '/tmp' date: '04-Dec-2022 11:34:26' bytes: 0 isdir: 1 datenum: 7.3886e+05
This refers to the parent of this directory, so cd .. will change into the parent directory of the current directory.
When I try to split the name of this first "file" into parts, what do I get?
[thepath, thename, theextension] = fileparts(D(1).name)
thepath = 0×0 empty char array thename = 1×0 empty char array
theextension = '.'
You probably want to filter out the directories. One way to do this would be to only move the file if files(id).isdir is not 1.
  5 Comments
Steven Lord
Steven Lord on 5 Dec 2022
Those commands would match MATLAB script, function, or class files in that directory. They don't match live scripts or live functions with the .mlx extension. They also wouldn't list MATLAB data files with the .mat extension, MATLAB figure files (.fig), Simulink model files, etc. I don't know if any of those are in scope.
Image Analyst
Image Analyst on 5 Dec 2022
Steve, correct. Since he said ""rename a lot of mfiles in a folder" I assumed it was only mfiles with a filename extension of ".m". If he wants other extensions, like .fig, he can append those on like this:
filePattern1 = fullfile(folder, '*.m') % Full demo in my answer below.
filePattern2 = fullfile(folder, '*.fig') % Full demo in my answer below.
fileList = [dir(filePattern1); dir(filePattern2)]
allFileNames = {fileList.name}

Sign in to comment.


Jan
Jan on 4 Dec 2022
Edited: Jan on 4 Dec 2022
folder = 'D:\something';
files = dir(folder);
files = file(~[files.isdir]); % Files only!
for k = 1:numel(files) % numel() is safer than lenght()
oldFile = files(k).name;
[~, name, ~] = fileparts(oldFile);
newFile = [upper(name), '.m'];
% Or maybe:
% newFile = oldfile;
% newFile(1) = upper(newFile(1));
... movefile(fullfile(folder, oldFile), fullfile(folder, newFile)) ?!?
end
Under Windows you cannot use MOVEFILE to rename a file, if only the case differs. "m1.m" and "M1.m" are considered as equal by the operating system (but not by Matlab).
Another solution is an indirection: Use movefile() to rename the file "m1.m" to "tmp_ThisIsAUniqueName1234" and then to "M1.m".
Before I can suggest explicit code for the renaming, you have to define the wanted modification exactly.
  2 Comments
Mohammad Shojaei Arani
Mohammad Shojaei Arani on 4 Dec 2022
Edited: Jan on 5 Dec 2022
Hi Jan,
Thanks for your help. You already fixed my first problem. So, now I can acess the file names inside for-loop. Great!
I do not like to use the idea in the file exchange (I have to spend an hour to see what it is). And, yes, I use windows.
To do the alternative idea I understood that I should change the file name from m1.m to something like temp.m and then to M1.m using the command movefile(). Shall I proceed as bellow?
folder = 'D:\something';
files = dir(folder);
files = file(~[files.isdir]); % Files only!
for k = 1:numel(files) % numel() is safer than lenght()
oldFile = files(k).name;
[~, name, ~] = fileparts(oldFile);
tempFile = replace(name,'m','temp');
newFile = replace(tempFile,'temp','M');
movefile(fullfile('D:\something', oldFile), fullfile('D:\something', newFile)
end
Jan
Jan on 5 Dec 2022
Edited: Jan on 5 Dec 2022
You do not have to change the contents of the variable twice, but the name of the file.
Unfortunately you still do not reveal, how you want to modify the name of the file. Should only the 'm' be converted to 'M'? Then:
folder = 'D:\something';
files = dir(folder);
files = file(~[files.isdir]); % Files only!
for k = 1:numel(files) % numel() is safer than lenght()
oldFile = files(k).name;
[~, name] = fileparts(oldFile);
newFile = [upper(name), '.m']; % Maybe?!?
tempFile = fullfile(folder, 'tempFile.tmp');
movefile(fullfile(folder, oldFile), tempFile); % 1st renaming
movefile(tempfile, fullfile(folder, newFile)); % 2nd renaming
end
Using the FileExchange submission FileRename is not hard: Either download the submission from the FileExchange and compile it by: mex -O FileRename.c, or download the pre-compiled mex file. Then:
folder = 'D:\something';
files = dir(folder);
files = file(~[files.isdir]); % Files only!
for k = 1:numel(files) % numel() is safer than lenght()
oldFile = files(k).name;
[~, name] = fileparts(oldFile);
newFile = [upper(name), '.m']; % Maybe?!?
FileRename(fullfile(folder, oldFile), fullfile(folder, newFile));
end
The FileExchange is full of gems. It is worth to learn how to use the tenthousand of useful submissions of other Matlab programmers.

Sign in to comment.

Categories

Find more on Testing Frameworks in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!