evalin('base', 'save('var1', 'var2')')

evalin('base', 'save('var1', 'var2')')
I am trying to run a simple function to save specific variables from the base.workspace to a specific location. The variable to be saved and the file name are stored in arrays within the function. As I am learning you can't save base.workspace from the function and you can't send function variables to the base.workspace with 'evalin'.
What is the best way to save base.workspace.array's from a function when the save variables are stored within the function. Do I need to create temp variable on the base.workspace, (I found 'assignin' or 'putvar') then remove. This needs to executed in a loop as my function cycles through the variables saving the relevant files, names to specific locations.
Full Code; NB fOut only used to check function variables are correct.
function fOut = saveData(filterIn)
%to save arrays in work space to C:\Users\Remote\Documents\MATLAB\DATA Files
cd('C:\Users\Remote\Documents\MATLAB\DATA Files');
cd1 = cd;
wSpace = evalin('base', 'whos');
arNames = cell(length(wSpace),1);
arNames = arrayfun(@(x)x.name(1,:), wSpace, 'uniformoutput', false);
if nargin >0
tempIdx = strfind(arNames, filterIn);
index = find(not(cellfun('isempty', tempIdx)));
else
index = find(not(cellfun('isempty', arNames)));
end
for iii = 1:length(index)
iiiTicker(iii,1) = arNames(index(iii,1),:);
iiiTickerChar{iii,1} = char(arNames(index(iii,1),:));
evalin('base', 'save(char(arNames(index(iii,1),:)), char(arNames(index(iii,1),:)))');
end
cd('C:\Users\Remote\Documents\MATLAB');
fOut.cd1 = cd1;
fOut.index = index;
fOut.filterIn = filterIn;
fOut.wSpace = wSpace;
fOut.arNames = arNames;
fOut.tempIdx = tempIdx;
fOut.index = index;
fOut.iii = iiiTicker;
fOut.iiiTickerChar = iiiTickerChar;

 Accepted Answer

Jan
Jan on 28 Dec 2011
The command looks nicer when written as:
evalin('base', 'save(arNames{index(iii,1),:}, arNames{index(iii,1),:})')
This will work if arName and iii is defined in the base-workspace as well as the variable with the name called arNames{index(iii,1),:}. But I assume, these variables are defined in the local workspace. Therefore I stringly recommend not to use evalin for such spoofing tricks.
[EDITED]: To create the command string, when arNames, index and iii are defined locally:
name = arNames{index(iii)};
evalin('base', sprintf('save(''%s'', ''%s'')', name, name));
As usual for eval and its evil brothers, enclose this command in a try, catch block and verify that name is a valid symbol, e.g. by:
if strcmp(genvarname(name), name) == 0
error('author:toolbox:badSymbol', ...
'Bad symbol: [%s]', name);
end
This will reduce the risk of a name like "system('format D:')". I do not think, that you use such names. But bugs happen. And by definition bugs are unexpected and have unexpected results. Then it is surely a wise idea to let them not use EVAL/EVALIN as a gun to shoot up your computer. However, avoid EVAL/EVALIN would even be smarter and it is always possible.

6 Comments

Jan,
Thanks you are correct the variables are defined in the function (local workspace). What would you recommend I use in order to save arrays in base.workspace using function variables.
I will edit my q? to include full code.
Thanks
AD
Jan
Jan on 28 Dec 2011
Trying to access variables in other workspaces is prone to error (as you can see) and hard to debug. To keep the code as simple and clear as possible, access only variables in the current workspace. If you really have to store a variable in the base-workspace for any unknown (but not nice) reason, forward them as inputs to your function, such that they are available locally. Then the command for saving is:
name = arNames{index(iii)};
save(name, name);
NOTE: I assume, that |arNames| is a {N x 1} cell string and |index| is a vector. Then the 2nd index can be omitted.
I have handfuls of arrays in my base.workspace from where they are returned from my own functions. Instead of saving my whole workspace as a 'struct' I wish to save each array in its own '.mat' file under different folders, maybe even date stamp the file names in order to track versions.
I have standardized my array naming so I have a suffix for a specific work stream, eg 'ABC...'. What I want to be able to do is
>>saveData('ABC');
and all my arrays of 'ABC' work stream are saved in the 'ABC' data folder.
Your right I realy don't want to be accessing/reading/writing variable to to and from base/local.workspaces. If I use 'assignin' or 'putvar' I could put the variables onto base.workspace so the save could access the variables. However I would rather call them from the function so I don't have to remove the variable from the base.workspace once done.
Could I print a string to the save function within the evalin, so a string is passed within save not a variable call.
NOTE: your correct.
Thanks,
AD
Jan
Jan on 28 Dec 2011
See [EDITED]
Jan
Thanks I got it to work.
FYI. evalin('base', sprintf('save(''%s'',''%s'')', nameTemp, nameTemp));
Save needs input as strings.
Before I accept your ans. Is there a better command or function to do this without using the evil twins.
Your description of the evil twins reminds me of old unix.chatroom days when someone would be convinced to run "mv -f \ \dev\null" on their new UNIX box. Ahh they were the days.
Jan
Jan on 28 Dec 2011
There is no better command, but a better design. If you want to save all variables in the base-workspace from a function, you need EVALIN. This has the disadvantage, that you cannot control, which variables are saved.
I'd prefer to store all variables belonging to a certain program in a struct. This struct can be used as input for the function for saving such that a simple SAVE command is working.

Sign in to comment.

More Answers (1)

Fangjun Jiang
Fangjun Jiang on 28 Dec 2011

0 votes

You need to pay attention to the syntax for using single quote inside the single quote. You could do.
evalin('base', 'save(''MyMatFile'', ''var1'')')
Note the first input argument for save() is the file name, not a variable name.

6 Comments

Sorry my mistake I explained incorrectly. My exact syntax is;
evalin('base', 'save(char(arNames(index(iii,1),:)), char(arNames(index(iii,1),:)))');
So what is the problem? As long as you specify the correct arguments for save(), it should work without the problem. You could try a simple example first.
Fangjin
Thanks, my save works, but when I run the elavin.save will take the variable names used in the save from the base.workspace not the function. I would like to use variable names calculated in the function to save files on the base.workspace.
I have now included complete code.
Thanks
If it is about file name, use movefile(), copyfile() or even the old fashion !ren
evalin('base', 'save(char(arNames(index(iii,1),:)), char(arNames(index(iii,1),:)))');
runs the 'save' in the base.workspace. The variables |arNames| and |index| exist in the local.function.workspace and are not transfered in evalin.
my function
1) finds arrays in base.workspace that meet search string
2) saves only those arrays using array names as save criteria.
I need save or something similar to be able to save from base.workspace whilst using local.function.variables.
There might be different ways to do it. But I am thinking since the variables are in base workspace, you might just run evalin('base','save(...)') and save it to a temporary file name. Then you can use movefile() to rename the file name according to the string name inside your function.

Sign in to comment.

Categories

Tags

Asked:

on 28 Dec 2011

Community Treasure Hunt

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

Start Hunting!