# How to get the directory of a package?

I have a package that I have placed in the $BaseDirectory\Applications directory so that Needs can find it. I have a logo in the directory that I will return when a function is called. However, when I call NotebookDirectory in the package I get the directory of the notebook (this seems like expected behavior). I've not been able to find a corresponding PackageDirectory function. How do I get the directory of a package so I can load a resource (in this case a .jpg logo) to return to the calling notebook? Update to show package and $InputFileName returns empty string

Update to show proper use of $InputFileName in package The package saved as an .m file in $BaseDirectory\Applications is:

BeginPackage["MyTest"];
packageDirectory::usage="Gets the directory of the this package.";
packageLogo::usage="Gets the logo of this package.";
testfoo::usage="does this work"
Begin["Private"];
(* $Input only has a value as the package is being loaded so capture that value with Set in order to use it with SetDelayed later. *) thisIsThePackageDirectory=$InputFileName//DirectoryName;
packageDirectory[]:=thisIsThePackageDirectory
packageLogo[]:=Import[FileNameJoin[{thisIsThePackageDirectory,"logo.jpg"}],"JPEG"]
testfoo[]:="some text"
End[];
EndPackage[];


The logo.jpg file is in the same directory as the .m package.

The notebook commands are as follows.

Needs["MyTest"]
Names["MyTest*"]
(* {"packageDirectory", "packageLogo", "testfoo"} *)
packageLogo[]
(* Logo image returned *)
packageDirectory[] // InputForm
(* "C:\\ProgramData\\Mathematica\\Applications\\MyTest.m" *)
testfoo[]
(* some text *)


Many thanks to @Szabolcs and @Ymareth.

FindFile will tell you which file will be loaded when you ask for a particular package with the backtick syntax.

DirectoryName will return the directory that contains a file.

Example:

In[1]:= FindFile["Combinatorica"]


Update: This solution is probably better: in your package file, use $InputFileName to determine the location of the package file and save it into a variable that is private to the package. The use this variable with the function that shows the logo. • $InputFileName returns an empty string. – Edmund Apr 11 '15 at 12:00
• I also think FindFile is a bit expensive to use. The system already knows where the package file is. It has loaded it after all. Why do another scan of the $Path directory hierarchies to "find" it and the strip the file name from it. – Edmund Apr 11 '15 at 12:55 •$InputFileName only has a value while the kernel is loading a package. So the package itself can do something with that filename while its being loaded. – Ymareth Apr 11 '15 at 14:17
• @Ymareth Ah! It is the difference between Set and SetDelayed in my package definitions. I understand now. I had to capture the value of $InputFileName//DirectoryName into a variable using Set. This executes when the package loads. Then I can use this variable anywhere in the SetDelayed defintions. However, I was using $InputFileName in the SetDelayed definitions and these don't run until alter the package as been loaded. Therefore, I was getting the empty string. – Edmund Apr 11 '15 at 14:30
• @Edmund That is what I meant by "use \$InputFileName to determine the location of the package file and save it into a variable that is private to the package". – Szabolcs Apr 11 '15 at 14:34