Changing specific characters in filenames across subfolders

6 views (last 30 days)
How can I change the first character "r" by another character "f" in all the filnames from multiple subfolders:
Directory folder1/folder2/folder3/
then, multiple files starting with "r" are located in multiple folders. Eg., (S001, S002) :
S001
rXXX11.nii
rXXX32.nii
S002
rXXX41.nii
rXXX63.nii
One unsuccesfull trial:
SourcePath ='D:\folder1\folder2\folder3\';
Participant = 'S';
index = 1001 : 1602;%Index the subjs according to their folder order (e.g., from 001 to 0602)
for i = 1 : length(index)
newParticipant=num2str(index(i));
newParticipant(1)='S';
%To setting the path's source folder iterating the subject folder
SourceFolder = fullfile([SourcePath,newParticipant]);
str=SourceFolder;
pat ='r*.nii';
newStr = replace(str,pat,'f*.nii');
end
Many thanks for any input.

Accepted Answer

Voss
Voss on 28 Dec 2022
@julian gaviria: To address the problems you ran into:
"1. Is not recursive."
That's true; however, it is intended to operate on all folders starting with "S" at once, and find .nii files starting with "r" in each such folder.
SourcePath = 'D:\folder1\folder2\folder3';
dinfo = dir(fullfile(SourcePath, 'S*', 'r*.nii'));
% ^^^^^^^^^^ main folder
% ^^^^ sub-folder starting with "S"
% ^^^^^^^^ .nii file in sub-folder starting with "r"
"2.the expression must be changed [from '\\r(\w+\.nii)' to '\\r(\w*)']"
That's not true.
'\\r(\w+\.nii)' matches a backslash followed by a lowercase "r" followed by one or more alphanumeric or underscore characters followed by ".nii". Therefore it matches file names starting with "r" and ending with ".nii", as long as the rest of the file name contains only alphanumeric characters or underscores.
'\\r(\w*)' matches a backslash followed by a lowercase "r" followed by zero or more alphanumeric or underscore characters. It's not limited to matching file names ending with ".nii", and in fact it's not even limited to matching file names (i.e., without the "\.nii" specified, it can match directory names too).
Consider:
% your proposed regular expression works ok on this file name:
regexprep('C:\Users\Docs\S1000\rkehwr.nii','\\r(\w*)','\\f$1')
ans = 'C:\Users\Docs\S1000\fkehwr.nii'
% but if any folder in the path happens to start with "r",
% you have a problem (here the "rocs" folder becomes "focs"):
regexprep('C:\Users\rocs\S1000\rkehwr.nii','\\r(\w*)','\\f$1')
ans = 'C:\Users\focs\S1000\fkehwr.nii'
The original works in both of those cases, because it is constrained by "\.nii" to match names of .nii files only:
regexprep('C:\Users\Docs\S1000\rkehwr.nii','\\r(\w+\.nii)','\\f$1')
ans = 'C:\Users\Docs\S1000\fkehwr.nii'
regexprep('C:\Users\rocs\S1000\rkehwr.nii','\\r(\w+\.nii)','\\f$1')
ans = 'C:\Users\rocs\S1000\fkehwr.nii'
But if you have file names that contain non-alphanumeric/underscore characters, they would be missed:
% "(" and ")" don't match the pattern -> file name is not changed
regexprep('C:\Users\Docs\S1000\rkehwr (Copy).nii','\\r(\w+\.nii)','\\f$1')
ans = 'C:\Users\Docs\S1000\rkehwr (Copy).nii'
% "#" doesn't match the pattern -> file name is not changed
regexprep('C:\Users\rocs\S1000\rk#hwr.nii','\\r(\w+\.nii)','\\f$1')
ans = 'C:\Users\rocs\S1000\rk#hwr.nii'
% "=" doesn't match the pattern -> file name is not changed
regexprep('C:\rUsers\Docs\S1000\rke=wr.nii','\\r(\w+\.nii)','\\f$1')
ans = 'C:\rUsers\Docs\S1000\rke=wr.nii'
A more general regular expression would be '\\r([^\\]*\.nii)', which will match a backslash followed by a lowercase "r" followed by zero or more non-backslash characters (that's the [^\\]* part) followed by ".nii". This way you're guaranteed to match the name of any .nii file that starts with "r". (Use non-backslash to match any base file name and avoid matching parent directory names.)
To show this regular expression on some of the previous examples:
% an easy case -> works
regexprep('C:\Users\Docs\S1000\rkehwr.nii','\\r([^\\]*\.nii)','\\f$1')
ans = 'C:\Users\Docs\S1000\fkehwr.nii'
% a folder starting with "r" -> works
regexprep('C:\Users\rocs\S1000\rkehwr.nii','\\r([^\\]*\.nii)','\\f$1')
ans = 'C:\Users\rocs\S1000\fkehwr.nii'
% a file name with special character(s) -> works
regexprep('C:\Users\rDocs\S1000\rkehwr (Copy).nii','\\r([^\\]*\.nii)','\\f$1')
ans = 'C:\Users\rDocs\S1000\fkehwr (Copy).nii'
"3. I do not manage to move/change the filenames."
Use cellfun since the file names are stored in cell arrays. (And you can omit "'uniform',0" since movefile returns a scalar.)
cellfun(@(OLD,NEW) movefile(OLD, NEW), filenames, newfilenames);
For completeness, the whole code (again, this code operates on all S* folders - do not put this code inside a loop) would be:
SourcePath = 'D:\folder1\folder2\folder3';
dinfo = dir(fullfile(SourcePath, 'S*', 'r*.nii'));
filenames = fullfile( {dinfo.folder}, {dinfo.name} );
newfilenames = regexprep(filenames, '\\r([^\\]*\.nii)', '\\f$1');
cellfun(@(OLD,NEW) movefile(OLD, NEW), filenames, newfilenames);

More Answers (1)

Walter Roberson
Walter Roberson on 19 Dec 2022
SourcePath ='D:\folder1\folder2\folder3';
dinfo = dir(fullfile(SourcePath', 'S*', 'r*.nii'));
filenames = fullfile( {dinfo.folder}, {dinfo.name} );
newfilenames = regexprep(filenames, '\\r(\w+\.nii)', '\\f$1');
arrayfun(@(OLD,NEW) movefile(OLD, NEW), filenames, newfilename, 'uniform', 0);
  1 Comment
julian gaviria
julian gaviria on 20 Dec 2022
Moved: Voss on 28 Dec 2022
Thank you @Walter Roberson. I encountered 3 issues in your suggestion:
1. Is not recursive. To recall the data structure:
Directory folder1/folder2/folder3/S001
Directory folder1/folder2/folder3/S002
...
Directory folder1/folder2/folder3/S080
2.the expression must be changed as follows (according to "regexprep" docummentation):
newfilenames = regexprep(filenames, '\\r(\w*)', '\\f$1');
3. I do not manage to move/change the filenames.
SourcePath ='D:\folder1\folder2\folder3\';
Participant = 'S';
index = 1001 : 1080;%Index the subjs according to their folder order (e.g., from 001 to 080)
for i = 1 : length(index)
newParticipant=num2str(index(i)); % THIS SHOULD HAVE BEEN USED
newParticipant(1)='S'; % Adding the suffix "S" and removing the first character to index
SourceFolder = fullfile([SourcePath,newParticipant]);
dinfo = dir(fullfile(SourceFolder, 'r*.nii'));
filenames = fullfile( {dinfo.folder}, {dinfo.name} );
newfilenames = regexprep(filenames, '\\r(\w*)', '\\f$1');
arrayfun(@(OLD,NEW) movefile(OLD, NEW), filenames, newfilenames, 'uniform', 0);
end
>> arrayfun(@(OLD,NEW) movefile(OLD, NEW), filenames, newfilenames, 'uniform', 0);
Error using movefile
Argument must be a text scalar.
Error in @(OLD,NEW)movefile(OLD,NEW)

Sign in to comment.

Categories

Find more on Operators and Elementary Operations in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!