File Exchange

image thumbnail

Recursive addpath

version 1.6 (3.54 KB) by

Recursively adds directories to MATLAB path, optionally ignores some

4.28571
12 Ratings

3 Downloads

Updated

View License

This is a very simple function that will add all directories beneath a specified directory (or the current directory if none is specified), with the option to ignore a specified list of directories. Any directories that are ignored (for instance, '.svn' and 'CVS' if using version control) will not have their subdirectories added either.

This is a fast, very lightweight--and easily modifiable--function that should work on any platform (not tested explicitly). I use it to add the directory trees of toolboxes not stored in MATLAB's toolbox folder, as well as for modules checked out of SVN and CVS source control repositories.

Per reviewer suggestions and comments, this now ignores private directories, overloaded methods directories, and also hidden directories with no need to specify additional directories. It also accepts flags as in 'addpath' to place the directories at the beginning or end of the path.

An addition to this function (12/01/2008) is the ability for it to be run in 'reverse', recursively removing directories from the path. This capability can be very useful when working with multiple copies of a code repository, for instance. Also, I fixed a bug as mentioned by a reviewer that properly handles files without extensions.

Thanks to the extensive help of a user (Joe McDonnell), this function has been almost totally rewritten with better error detection, more efficient operation (much quicker run times, even for large directory trees), an extended debug mode that lists everything the function does, and better help. Also, now ignores the 'CVS' directories by default.

Another user (Jim) made a suggestion which resulted in a speed increase of approximately 3x in a moderate-sized directory tree (which should increase with larger sized trees). Also, a small change is made for Mac compatibility.

Comments and Ratings (18)

Kris Janssen

I still find this function useful. However, in it's current form it results in console warnings when e.g. package folders (those starting with a '+') are picked up.

To remedy this I inserted two quick lines (I included two lines of the original for reference):

%Build the list of directories
caAddRemDirs = {};
[caAddRemDirs] = addpath_recursively(caAddRemDirs, strStartDir, caStrsIgnoreDirs, strXorIntAddpathMode, blnRemDirs,blnDebug);

%KJ: find all module dirs (with a '+' in the name).
matches = strfind(caAddRemDirs,'+');
%Retain folders with no match for '+'
caAddRemDirs = caAddRemDirs(cellfun(@isempty,matches));

Warnings gone!

David G

Excelent!

Miguel

Miguel (view profile)

Pearl

Pearl (view profile)

Anthony Kendall

Thanks Jim!

I made that change for compatibility with Macs. Also, based on your first comment back in October I increased the speed of the code by a factor of 3 in a moderate-sized directory tree.

Jim Hokanson

Jim Hokanson (view profile)

It seems I can't figure out how to work this comment system. The main point of the last post was that the code doesn't work on a MAC as strStarDir\*. doesn't work, it only returns . and ..

Jim Hokanson

Jim Hokanson (view profile)

OOPS, that second part should read:
saSubDirs = dir(strStartDir);
saSubDirs = saSubDirs([saSubDirs.isdir]);

Jim Hokanson

Jim Hokanson (view profile)

Jim Hokanson

Jim Hokanson (view profile)

Just to clarify on that last point, keeping a cell array of all directories to process, then using addpath(pathsOut{:},strXorIntAddpathMode) (where pathsOut is a cell array of all paths to add) works well

Sven

Sven (view profile)

You can avoid the first bug I mentioned above by adding the following at line 59:
currDir = currDir([currDir.isdir]);

Oh, and I just checked in genpath, and see that IT uses recursive calls to 'dir'. Therefore my second suggestion doesn't actually avoid these multiple calls!

Sven

Sven (view profile)

Thank you for this very useful function. I have two main comments:
1. I think that there's a bug that causes the function to crash if a file without ANY extension is in a directory. For example, some people submit file exchange packages that include a file called "README". Your function fails on this case (at the moment).

2. I haven't checked yet, but perhaps this could be rewritten without using recursive functions. I think that if you simply use genpath to get a list of directories, you could then filter this list all in one go. This may be a little faster.

Nice function!

Thierry Dalon

Be aware: you are using assert function. This is not available in R14 or previous!
Moreover I am not sure if assert exit the function...

Thierry Dalon

it is not possible to change a rating in this new FX...sorry for the previous rating.
I think now it is a very useful file. Thanks for updating!
One last suggestion: I would consider a default ignore value possible in the script. For example, if no ignore input argument use ignore = {'.svn'}, editable by the user so that users can simply call your file without passing always an ignore option if they have a predilected default value.

Thierry Dalon

Thierry Dalon

@Author: the idea of an ignore option is good.
Good would be if you could also directly pass through ignore filter like "all directories starting wih "@" or "#"". At the best would be generic wildcard expressions.
Small missing point:Your implementation does not allow to use addpath intrinsec option like -BEGIN and -END.
You removed some features from original Matlab GENPATH which make your version not optimized. (private and @ not ignored by default; your loop run also over all files!)
------
@Jesse: this can be done with a small correction in the code:
if ~any(strcmp(currDir(m).name,{'.','..',ignore{:}})) && currDir(m).isdir && ~strncmp(currDir(m).name,'@',1) && ~any(strcmp(currDir(m).name,{'private','.',,'..')) ...
(see also original GENPATH)

Jesse Hopkins

Works pretty good, but it doesn't automatically ignore "private" directories and "@" directories like genpath does. You can easily add "private" to the list of ignored directories, however being able to skip over all "@" directories requires some code change.

Anthony Kendall

Genpath is unable to ignore directories, which is a key feature for certain uses (like source code repositories). That's the real utility of this function.

B. Roossien

What is wrong with addpath(genpath())?

Updates

1.6

Optimizations and Mac compatibility changes.

1.5

Extensive modifications to code, renamed variables, better input checking, error checking, a debug mode, more examples, better help.

1.4

Added new capability to recursively remove directories, fixed a small bug.

1.3

Made changes to reflect reviewer comments. Thanks!

MATLAB Release
MATLAB 7.6 (R2008a)
Acknowledgements

Inspired: genpath_exclude

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video