9

Now I am writing a small package. I have written several files and put them in the same directory. And some files need to read in or include another file in the same directory. But when I simply write the file name there, Mathematica can not find them. Is there a easy way to keep this portability? Thank for your kindly help!

wxg
  • 443
  • 3
  • 9

3 Answers3

14

The solution using SetDirectory / ResetDirectory, given by @celtschk, is perfectly valid. However, personally I try to avoid this method, since you have to be sure that no other piece of code resets the directory during your operations.

Here is an alternative method. There are two cases we can distinguish here:

  1. You are talking about various .m files, into which you split your package. In this case, you can use a very useful system variable $InputFileName, which returns the full name of the file currently being read. For example, if you read in the following package

    BeginPackage["Test`"]
    
    $location = $InputFileName
    
    EndPackage[]
    

    then the Test`$location variable will contain the full name of the file containing that package. You can then extract the name of the directory as

    DirectoryName[$InputFileName]
    

    and use that to load other files in the same directory.

  2. If you need this for other types of files, such as text files etc, then you will need a full name for at least one such file in any case. Having that, you can also extract the directory name, and use if for other files.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • [service message] The "@" before a user name has no function in questions or answers, only in comments. They serve to notify that user of the comment, but only if he commented on that same answer earlier. Only one user can be notified of a comment this way. Poster of the answer will always be notified. – stevenvh Sep 29 '12 at 17:53
  • @stevenvh Thanks, I know this. I am just using this for the reference to some person to stand out in the text. We used this style some time ago while being a tag on SO, not sure if anyone else is still using it here. Let me know if for some reason you find it inappropriate. – Leonid Shifrin Sep 29 '12 at 17:55
  • No, by no means inappropriate! I just think it looks funny :-). I didn't know you knew. I usually type user names in my posts in italic; not all user names are identifiable as such. But you don't have to change your habits for me! :-) – stevenvh Sep 29 '12 at 18:07
  • @stevenvh What?! I didn't know that! – xzczd Sep 30 '12 at 02:32
  • @Leonid Shifrin: Thank you very much! This is just what I need. I also find SystemPrivate$InputFileName for a substitution in M7 from another answer of you. – wxg Sep 30 '12 at 03:18
  • @wxg Glad I could help. Thanks for the accept. – Leonid Shifrin Sep 30 '12 at 16:30
  • Keep in mind that $InputFileName is set when Get is running. So if you define your package some way other than Needs or Get, e.g. if you have your package code in an input cell and Shift-Evaluate it, that variable will not be set. – Joel Klein Feb 14 '13 at 23:00
  • @JoelKlein Thanks, I am aware of that. – Leonid Shifrin Feb 14 '13 at 23:07
  • Oh, I'm sure you are, I just meant anybody else reading this answer. :) – Joel Klein Feb 15 '13 at 04:19
6

The solution is to use SetDirectory and ResetDirectory to temporarily set the working directory to the one with your files. For example:

SetDirectory["where/your/files/are"]

<<foo.m

DoSomethingWith["bar.txt"]

ResetDirectory[] (* set the working directory to whatever it was before *)

Note that SetDirectory maintains a stack of previous values, so you can use several nested SetDirectory/ResetDirectory pairs.

celtschk
  • 19,133
  • 1
  • 51
  • 106
0

I use this function that works both to notebooks and scripts:

setDir:=Quiet@Check[SetDirectory@DirectoryName@$InputFileName,SetDirectory@NotebookDirectory[]]

So you can test your script in the command line and in the notebook. For more advanced implementation I recomend Leonid answer.

Murta
  • 26,275
  • 6
  • 76
  • 166