5

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?

Jason Gross
  • 589
  • 2
  • 10

3 Answers3

7

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.

LouisB
  • 12,528
  • 1
  • 21
  • 31
3

$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.

Itai Seggev
  • 14,113
  • 60
  • 84
0

Indeed, NotebookDirectory[] does not work in the script environment.

In a script environment, just replace NotebookDirectory[] by Directory[].

In a script environment, the output of Directory[] is the path of the script file (or the path from where you started the wolframscript session).

If for some reason you want a command to work in both notebook and script environments, then this should work:

Quiet@If[
  NotebookDirectory[] === $Failed, 
  Directory[], 
  NotebookDirectory[]
];

Or, as suggested by @Rolf Mertig,

If[$Notebooks, NotebookDirectory[], Directory[] ]

Note: I am running WolframScript from WolframEngine 12.2.0.

Davi
  • 671
  • 3
  • 13