MATLAB copyfile error: argument must contain a string - matlab

So I have a pretty simple problem I'm trying to solve. I want to create a backup of a file in MATLAB.
Here is my code (I am starting this script from my current directory):
backup_dir=strcat(pwd,'/backups/');
cd('../../source_destination/');
source_dir=pwd;
cd(backup_dir);
source_files=strcat(source_dir,'/*.m');
source_file_list=dir(source_files);
source_file_names={source_file_list.name}';
for i=1:numel(source_file_names)
source_file=strcat(source_dir,'/',source_file_names(i));
backup_file=strcat(backup_dir,source_file_names(i));
copyfile(source_file,backup_file);
end
Running this gives me the error:
Error using copyfile
Argument must contain a string.
However, when I actually examine source_file and backup_file, both variables return a valid string (enclosed by ' ') and both strings do point to a valid file:
>> source_file
source_file =
'/Users/me/mydir/cool/source_destination/archive.m'
>> backup_file
backup_file =
'/Users/me/mydir/cool/world/scripts/backups/archive.m'
Also, the actual content of source_file_list is valid.
So why would I be getting this error?

You need to dereference the cell array contents with curly braces, otherwise strcat returns a cell array of strings:
for i=1:numel(source_file_names)
source_file=strcat(source_dir,'/',source_file_names{i});
backup_file=strcat(backup_dir,source_file_names{i});
copyfile(source_file,backup_file);
end

Related

Having trouble conditionally moving files based on their names

I am trying to write a script that will auto sort files based on the 7th and 8th digit in their name. I get the following error: "Argument must be a string scalar or character vector". Error is coming from line 16:
Argument must be a string scalar or character vector.
Error in sort_files (line 16)
movefile (filelist(i), DirOut)
Here's the code:
DirIn = 'C:\Folder\Experiment' %set incoming directory
DirOut = 'C:\Folder\Experiment\1'
eval(['filelist=dir(''' DirIn '/*.wav'')']) %get file list
for i = 1:length(filelist);
Filename = filelist(i).name
name = strsplit(Filename, '_');
newStr = extractBetween(name,7,8);
if strcmp(newStr,'01')
movefile (filelist(i), DirOut)
end
end
Also, I am trying to make the file folder conditional so that if the 10-11 digits are 02 the file goes to DirOut/02 etc.
First, try avoid using the eval function, it is pretty much dreaded as slow and hard to understand. Specially if you need to create variables. Instead do this:
filelist = dir(fullfile(DirIn,'*.wav'));
Second, the passage:
name = strsplit(Filename, '_');
Makes name a list, so you can access name{1} or possibly name{2}. Each of these are strings. But name isn't a string, it is a list. extractBetween requires a string as an input. That is why you are getting this problem. But note that you could have simply done:
newStr = name(7:8);
If name was a string, which in Matlab is a char array.
EDIT:
Since it has been now claimed that the error occurs on movefile (filelist(i), DirOut), the likely cause is because filelist(i) is a struct. Wheres a filena name (char array) should have been given at input. The solution should be replacing this line with:
movefile(fullfile(filelist(i).folder, filelist(i).name), DirOut)
Now, if you want to number the output folders too, you can do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,name(7:8)])
This will move a file to /DirOut/01. If you wanted /DirOut/1, you could do this:
movefile(fullfile(filelist(i).folder, filelist(i).name), [DirOut,filesep,int2str(str2num(name(7:8)))])

Loading files in a for loop in matlab

I am trying to load different file names contained in a matlab vector inside a for loop. I wrote the following:
fileNames = ['fileName1.mat', ..., 'fileName_n.mat'];
for i=1:n
load(fileNames(i))
...
end
However, it doesn't work because fileNames(i) returns the first letter of the filename only.
How can I give the full file name as argument to load (the size of the string of the filename can vary)
Use a cell instead of an array.
fileNames = {'fileName1.mat', ..., 'fileName_n.mat'};
Your code is in principle a string cat, giving you just one string (since strings are arrays of characters).
for i=1:n
load(fileNames{i})
...
end
Use { and } instead of parentheses.

Return a String value from my popup menu in MatLab

I am developing a simple GUI with MATLAB (guide) with a pop up menu in it. In order to establish a connection through a serial port.
function sendLog_OpeningFcn(hObject, eventdata, handles, varargin)
set(handles.popupmenuSerialPort,'String', {'''COM1''','''COM2''','''COM3''','''COM4'''});
...
I would like to get the selected value in this way:
serialPortList = get(handles.popupmenuSerialPort,'String');
serialPortValue = get(handles.popupmenuSerialPort,'Value');
serialPort = serialPortList(serialPortValue);
disp('serialPort ' + serialPortValue);
But I get an error message on disp function:
Undefined function 'plus' for input arguments of type 'cell'.
Invalid PORT specified.
How could I get the chosen value?
I hate to plow through 2 answers that are clearly not bad, but here the devil is in the details. Yes, you cannot concatenate strings in MATLAB with the + operator, but the first red flag in your question is that your error message indicates a cell as one of the arguments to +. Note that disp has not even thrown an error at this point, it was +. This leads me to believe that your code is actually disp('serialPort ' + serialPort); not disp('serialPort ' + serialPortValue); since serialPortList is a cell array. Was this a typo?
So, by indexing it like serialPort = serialPortList(serialPortValue); you get a single cell in serialPort, which would not work with proper string concatenation or disp. The correction here is to use the curly braces ({}).
Together with valid string concatenation,
>> serialPort = serialPortList{serialPortValue};
>> disp(['serialPort ' serialPort])
serialPort 'COM3'
The single quotes are in the string because of how you set the strings with set(handles.popupmenuSerialPort,'String',..., so if you want to strip that, you can use strrep(serialPort,'''','').
Note that you can also use fprintf if you are more comfortable with that style of string formatting.
You can't use '+' to combine strings in matlab.
you can do:
disp(['serialPort',num2str(serialPortValue)]);
Try array concatenation :
disp(['SerialPort : ' serialPortValue]);

How to store the line matching an expression in matlab

I have the following code, and i am wanting to store the entire line that contains the matching expression, but currently i am able to store only the expression itself.
expr='\hello';
fileread = regexp(filetext, expr, 'match');
fid = fopen('data.txt', 'wt');
fprintf(fid, '%s\n',fileread{:});
suppose my file contains:
Hello,my name is X
X hello
Not this line
my file data.txt stores
hello
hello
instead of the entire line containing the expression.
desired data.txt
Hello,my name is X
X hello
what am i doing wrong?
Based on the way you are interacting with the regexp function I will assume you have all the file text in a single variable. Let's imagine that variable takes the following form:
my name is hello there
Hello,my name is X
X hello
Not this line
For your reference, I've constructed this variable using sprintf
string = sprintf('my name is hello there\nHello,my name is X\n X hello\n Not this line')
You can extract the lines which have hello with the following regexp:
[~,~,~,d] = regexp(string, '.*?[H|h]ello.*?\n')
The results can be retrieved from the cell array with:
>> d{1}
ans =
my name is hello there
>> d{2}
ans =
Hello,my name is X
>> d{3}
ans =
X hello
Note that I used a couple of lazy quantifiers .*?, check out Laziness Instead of Greediness at this link if you would like to learn more: http://www.regular-expressions.info/repeat.html
What you're doing wrong is not using the MATLAB regexp function correctly. If you look under "Return Substrings using 'match' Keyword" on this site, you will see that the result you got is what is expected for what your code stated (it returns the parts of the input string that match the regular expression you supplied). I was going to post a suggestion, but someone beat me to it ;-). Good luck.

why strcat() doesn't return a string in Matlab?

I'm trying to access multiple files in a for loop, like this:
age = xlsread(strcat('Pipeline_BO_2013_',names(2),'_CDBU.xlsx'), 'Data', 'H:I')
It returns an error the filename must be string. So I did following test:
filename = strcat('Pipeline_BO_2013_',names(2),'_CDBU.xlsx')
filename =
'Pipeline_BO_2013_0107_CDBU.xlsx'
isstr(filename)
ans =
0
This is so weird. Could any one help me out? Thank you so much.
It looks like names is a cellstr and not a char array. If so, indexing in to it with parentheses like names(2) will return a 1-long cellstr array, not a char array. And when strcat is called with any of its arguments as a cellstr, it returns a cellstr. Then xlsread errors because it wants a char, not a cellstr.
Instead of just calling isstr or ischar on filename, do class(filename) and it'll tell you what it is.
Another clue is that filename is displayed with quotes. This is how cellstrs are displayed. If it were a char array, it would be displayed without quotes.
If this is the case, and names is a cellstr, you need to use {} indexing to "pop out" the cell contents.
filename = strcat('Pipeline_BO_2013_',names{2},'_CDBU.xlsx')
Or you can use sprintf, which you may find more readable, and will be more flexible once you start interpolating multiple arguments of different types.
filename = sprintf('Pipeline_BO_2013_%s_CDBU.xlsx', names{2})
% An example of more flexibility:
year = 2013;
filename = sprintf('Pipeline_BO_%04d_%s_CDBU.xlsx', year, names{2})