2
$\begingroup$

This is basically Analogue of NotebookDirectory[] for scripts (to get the directory path of my script.m)? or Write a mathematica script that returns the absolute path to its directory or How to set the relative directory so that they work both in script and in notebook and portable?, except that none of the answers given there work when my file starts with

#!/usr/bin/env wolframscript

and I run it as ./file.wls.

For example, this file:

$ cat file.wls
#!/usr/bin/env wolframscript
Print["$InputFileName: '"<>$InputFileName<>"'"];
Print["$Input: '"<>$Input<>"'"];
Print["NotebookDirectory[]: '"<>NotebookDirectory[]<>"'"];
$ ./file.wls
$InputFileName: ''
$Input: ''

FrontEndObject::notavail:
   A front end is not available; certain operations require a front end.

StringJoin::string:
   String expected at position 2 in NotebookDirectory[]: '<>$Failed<>'.
StringJoin[NotebookDirectory[]: ', $Failed, ']

$ echo |wolframscript
Wolfram Language 11.2.0 Engine for Linux x86 (64-bit)
Copyright 1988-2017 Wolfram Research, Inc.

In[1]:= In[1]:=

How do I make this work?

$\endgroup$
4
$\begingroup$

Here is a WolframScript that prints its own file name and directory:

#!/usr/bin/env wolframscript

(* Script assumptions :
    1.  User has Linux pgrep command installed
    2.  There is only one WolframScript running
    3.  Script has not changed directories, as with SetDirectory[]
    4.  Mathematica 11.0, or later
*)

pgrep = RunProcess[{"pgrep", "-a", "wolframscript"}];

scriptRelativePath = Last[StringSplit[ pgrep["StandardOutput"], " " ]];

scriptPath = ExpandFileName[ FileNameJoin[{Directory[], scriptRelativePath}] ];

scriptDirectory = DirectoryName[ scriptPath ];

scriptName = Last[FileNameSplit[ scriptPath ]];

Print[scriptPath]
Print[scriptRelativePath]
Print[scriptName]
Print[scriptDirectory]

Improvement

Using only WolframScript we can code:

#!/usr/bin/env wolframscript

(* Script assumptions :
    1.  Script has not changed directories, as with SetDirectory[]
    2.  Mathematica 11.0, or later
*)

scriptPath = ExpandFileName[First[$ScriptCommandLine]];
scriptName = Last[FileNameSplit[ scriptPath ]];

Print[scriptPath];
Print[scriptName];

The trick is to use $ScriptCommandLine.

$\endgroup$
  • $\begingroup$ Is there really no standard way to do this internally, without querying the OS? $\endgroup$ – Jason Gross Dec 26 '17 at 17:52
  • $\begingroup$ @JasonGross See the new "Improvement" section of my answer. $\endgroup$ – LouisB Dec 26 '17 at 20:09
  • $\begingroup$ scriptPath = ExpandFileName[Last[$ScriptCommandLine]]; should be scriptPath = ExpandFileName[First[$ScriptCommandLine]]; (i.e, Last should be First) $\endgroup$ – Itai Seggev Dec 27 '17 at 4:08
  • $\begingroup$ Thank you, @ItaiSeggev ! $\endgroup$ – LouisB Dec 27 '17 at 4:58
2
$\begingroup$

$ScriptCommandLine is what you want. It gives the command that launched the script. As noted in the other answer, if you want an absolute file name you'll need to expand the first argument.

The fact that $InputFileName is empty if a normal wolframscript is correct. See my answer to Difference between "wolframscript -f" and "wolframscript -script"

If using $InputFileName is important to you, you can add -script to the command line, but then you run the risk that it won't run at all on Linux due to difference in handling white space. Alternatively, on Linux you can use !#/usr/bin/wolframscript -script, but this won't run on OS X or Windows Unix-like environments.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.