Rake file task with 100s of files - rake

I'm just now learning about file tasks in Rake. I have 100s of javascript source files, that get concatenated to 10 or so files. I see this kind of mapping can be done intelligently with file tasks. It appears you need to specify every file.
Is there an efficient way to write a file task that recursively finds all of these javascript files and compare them to the concatenated files on the right side? The concatenation part is a tricky step and is being done by a custom build tool at the moment until I can get that in ruby.
For example,
/a.js
/c.js -----------> base.js
/geo/b.js
/geo/c.js -----------> geo.js
/mod/d.js
/mod/e.js -----------> mod.js

file 'base.js' => Dir['*.js'] do |t|
concatenate t.prerequisites, t.name
end
file 'geo.js' => Dir['geo/*.js'] do |t|
concatenate t.prerequisites, t.name
end
and so on, you will have to implement the concatenate method yourself, obviously (in my example the first argument is the list of files and the second is the destination file, e.g. geo.js). If all created files are named after directories you can do something like this:
%w(geo mod xyz abc).each do |module|
file "#{module}.js" => Dir["#{module}/*.js"] do |t|
concatenate t.prerequisites, t.name
end
end
If the directories can be globbed somehow you could make it even more dynamic by replacing the list of directory names with Dir[...] too.

How to invoke this rake file task?
%w(geo mod xyz abc).each do |module|
file "#{module}.js" => Dir["#{module}/*.js"] do |t|
# some code
end
end
rake ????

Related

saving multiple fields of structure as separate mat files and creating directory non-existing directories

There are two parts of my query
1) How to save different fields of structures as separate files(each file containing only named field of structure )?
2) Forcing save command to create directories in the save path when intermediate directories do not exist?
For first part:
data.a.name='a';
data.a.age=5;
data.b.name='b';
data.b.age=6;
data.c.name='c';
data.c.age=7;
fields=fieldnames(data);
for i=1:length(fields)
save(['E:\data\' fields{i} '.mat'],'-struct','data');
end
I want to save each field of struct data as a separate .mat file. So that after executing the loop, I should have 3 files inside E:\data viz. a.mat,b.mat and c.mat and a.mat contains only data of field 'a', b.mat contains only data of field 'b' and so on.
When I exeucte the above code, I get three files in my directory but each file contains identical content of all three variables a, b and c, instead of individual variables in each file.
Following command does not work:
for i=1:length(fields)
save(['E:\data\' fields{i} '.mat'],'-struct',['data.' fields{i} ]);
end
Error using save
The argument to -STRUCT must be the name of a scalar structure variable.
Is there some way to use save command to achieve my purpose without having to create temporary vaiables for saving each field?
For Second Part:
I have large number of files which need to stored in a directory structure. I want following to work.
test='abcdefgh';
save(['E:\data\' test(1:2) '\' test(3:4) '\' test(5:6) '\result.mat'])
But it showing following error
Error using save
Cannot create 'result.mat' because 'E:\data\ab\cd\ef' does not exist.
If any intermediate directory are not present, then they should be created by save command. I can get this part to work by checking if directory is present or not using exist command and then create directory using mkdir. I am wondering if there is some way to force save command to do the work using some argument I am not aware of.
Your field input argument to save is wrong. Per the documentation, the format is:
'-struct',structName,field1,...,fieldN
So the appropriate save syntax is:
data.a.name='a';
data.a.age=5;
data.b.name='b';
data.b.age=6;
data.c.name='c';
data.c.age=7;
fields = fieldnames(data);
for ii = 1:length(fields)
save(['E:\data\' fields{ii} '.mat'], '-struct', 'data', fields{ii});
end
And no, you cannot force save to generate the intermediate directories. Check for the existence of the save path first and create it if necessary.

MATLAB: Save figure with default name

I am running a matlab-script that produces a figure. To save this figure I use:
print(h_f,'-dpng','-r600','filename.png')
What this means is that if I don't change filename for each time I run the script, the figure filename.png will be overwritten.
Is there a way to save a figure to a default name, e.g. untitled.png, and then when the script is run twice it will make a new figure untitled(1).png instead of overwriting the original one?
You could create a new filename based on the number of existing files
defaultName = 'untitled';
fileName = sprintf('%s_%d.png', defaultName, ...
length(dir([defaultName '_*.png'])));
print(h_f,'-dpng','-r600', fileName)
Add a folder path to your dir search path if the files aren't located in your current working directory.
This will create a 0-index file name list
untitled_0.png
untitled_1.png
untitled_2.png
untitled_3.png
...
You could also use tempname to generate a long random name for each iteration. Unique for most cases, see section Limitations.
print(h_f,'-dpng','-r600', [tempname(pwd) '.png'])
The input argument (pwd in the example) is needed if you do not want to save the files in your TEMPDIR
You can try something like this:
for jj=1:N
name_image=sscanf('filename','%s') ;
ext=sscanf('.png','%s') ;
%%do your stuff
filename=strcat(name_image,num2str(jj),ext);
print(h_f,'-dpng','-r600',filename)
end
If you want to execute your script multiple time (because you don't want to use a "for") just declare a variable (for example jjthat will be incremented at the end of the script:
jj=jj+1;
Be careful to don't delete this variable and, when you start again your script, you will use the next value of jj to compose the name of the new image.
This is just an idea

How to remove a pattern from filename in Matlab

I'd like to remove '-2' from the filenames looking like this:
EID-NFBSS-2FE454B7-2_TD.eeg
EID-NFBSS-2FE454B7-2_TD.vhdr
EID-NFBSS-2FE454B7-2_TD.vmrk
EID-NFBSS-3B3BF9FA-2_BU.eeg
EID-NFBSS-2FE454B7-2_PO.txt
So as you may see the names of the files are different and there are different kind of extensions as well. All what I want to do is remove '-2' from all of the filenames. I was trying use this:
pattern = '-2';
replacement = '';
regexprep(filename,pattern,replacement)
and I got the results in the console, but after many attempts I have no idea how to 'say' to MATLAB switch the filnames in the same location.
#excaza hit it right on the money. You'll have to probe your desired directory for a list of files via dir, then loop through each filename and remove any occurrences of -2, then use movefile to rename the file, and delete to delete the old file.
Something like this comes to mind:
%// Get all files in this directory
d = fullfile('path', 'to', 'folder', 'here');
directory = dir(d);
%// For each file in this directory...
for ii = 1 : numel(directory)
%// Get the relative filename
name = directory(ii).name;
%// Replace any instances of -2 with nothing
name_after = regexprep(name, '-2', '');
%// If the string has changed after this...
if ~strcmpi(name, name_after)
%// Get the absolute path to both the original file and
%// the new file name
fullname = fullfile(directory, name);
fullname_after = fullfile(directory, name_after);
%// Create the new file
movefile(fullname, fullname_after);
%// Delete the old file
delete(fullname);
end
end
The logic behind this is quite simple. First, the string d determines the directory where you want to search for files. fullfile is used to construct your path by parts. The reason why this is important is because this allows the code to be platform agnostic. The delineation to separate between directories is different between operating systems. For example, in Windows the character is \ while on Mac OS and Linux, it's /. I don't know which platform you're running so fullfile is going to be useful here. Simply take each part of your directory and put them in as separate strings into fullfile.
Now, use dir to find all files in this directory of your choice. Replace the /path/to/folder/here with your desired path. Next, we iterate over all of the files. For each file, we get the relative filename. dir contains information about each file, and the field you want that is most important is the name attribute. However, this attribute is relative, which means that only the filename itself, without the full path to where this file is stored is given. After, we use regexprep as you have already done to replace any instances of -2 with nothing.
The next point is important. After we try and change the filename, if the file isn't the same, we need to create a new file by simply copying the old file to a new file of the changed name and we delete the old file. The function fullfile here helps establish absolute paths to where your file is located in the off-chance that are you running this script in a directory that doesn't include the files you're looking for.
We use fullfile to find the absolute paths to both the old and new file, use movefile to create the new file and delete to delete the old file.

MatLab list files (excluding directories) in a folder

So I know I can list all the files and directories in my current folder using functions like dir() or ls(), and I know once listed, I can tell them from each other with the field isdir.
But is there a way to exclude the directories from the very beggining and list the files alone?
Even better, is there a way to exclude the current . and parent .. directories -that will (of course) show everytime- and list every other file and directory? Seriously, who uses ls() wondering if . is there?
The output of dir is whatever the operating system is feeding it. So it might be different depending on what system you're running. Here is my approach to that:
list=dir();
CleanList=setdiff({list.name},{'.','..'})';
I'm not sure if there is a built in method for this, but why not write a custom function to do what you want?
Such as:
function list = files_dir(varargin)
% Similar functionality to 'dir', but only returns files (no folders)
list = dir(varargin{:});
list([list.isdir]) = [];
You can then customise this to perform other functionality, such as excluding hidden files.
And for your second request, where directories '.' and '..' are excluded:
function list = dir_exclude_self(varargin)
% same as 'dir', but doesn't return '.' or '..'
list = dir(varargin{:});
self_indices = ismember({list.name}, {'.', '..'});
list(self_indices) = [];
If you put functions like this in a specific place on your computer you can ensure they are always available to use by adding them to the MATLAB path in your startup.m file.

Matlab publish - Want to use a custom file name to publish several pdf files

I have several data log files (here: 34) for those I have to calculate some certain values. I wrote a seperate function to publish the results of the calculation in a pdf file. But I only can publish one file after another, so it takes a while to publish all 34 files.
Now I want to automize that with a loop - importing the data, calculate the values and publish the results for every log file in a new pdf file. I want 34 pdf files for every log file at the end.
My problem is, that I couldn't find a way to rename the pdf files during publishing. The pdf file is always named after the script which is calculating the values. Obviously the pdf is overwritten within a loop. So at the end everything is calculated, but I only have the pdf from the last calculated log file.
There was this hacky solution to change the Matlab publish script, but since I don't have admin rights I can't use that:
"This is really hacky, but I would modify publish to accept a new option prefix. Replace line 93
[scriptDir,prefix] = fileparts(fullPathToScript);
with
if ~isfield(options, 'prefix')
[scriptDir,prefix] = fileparts(fullPathToScript);
else
[scriptDir,~] = fileparts(fullPathToScript);
prefix = options.prefix; end
Now you can set options.prefix to whatever filename you want. If you want to be really hardcore, make the appropriate modifications to supplyDefaultOptions and checkOptionFields as well."
Any suggestions?
Thanks in advance,
Martin
Here's one idea using movefile to rename the resultant published PDF on each iteration:
for i = 1:34
file = publish(files(i)); % Replace with your own command(s)
[pathStr,fileName,ext] = fileparts(file);
newFile = [pathStr filesep() fileName '_' int2str(i) ext]; % Example: append _# to each
[success,msg,msgid] = movefile(file,newFile);
if ~success
error(msgid,msg);
end
end
Also used are fileparts and filesep. See this question for other ways to rename and move files.