Function Repository Resource:

DirectoryBlock

Source Notebook

Temporarily change the current directory for an evaluation and ensure that it is restored when evaluation is completed

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["DirectoryBlock"][expr]

evaluates expr, returning the result and restores any changes to the current Directory[] or DirectoryStack[] that may have occurred during evaluation of expr.

ResourceFunction["DirectoryBlock"][dir,expr]

uses dir as the initial working directory when evaluating expr.

Details and Options

ResourceFunction["DirectoryBlock"] restores the values of Directory[] and DirectoryStack[] after evaluating expr; it does not prevent changing directory during evaluation.
ResourceFunction["DirectoryBlock"] avoids the need to explicitly use ResetDirectory if using SetDirectory in expr.
ResourceFunction["DirectoryBlock"][dir,expr,CreateIntermediateDirectoriesTrue] will create the directory dir if it does not already exist.

Examples

Basic Examples (2) 

Evaluate code and restore the current working directory when complete:

In[1]:=
Directory[]
Out[1]=
In[2]:=
ResourceFunction["DirectoryBlock"][SetDirectory[$TemporaryDirectory]; Directory[]]
Out[2]=

Verify that the current directory is restored:

In[3]:=
Directory[]
Out[3]=

Specify a working directory to start from:

In[4]:=
dir = CreateDirectory[]
Out[4]=
In[5]:=
ResourceFunction["DirectoryBlock"][dir, Export["file.wl", "hello world"]]
Out[5]=

The file was created in the specified directory:

In[6]:=
file = FileNameJoin[{dir, "file.wl"}]
Out[6]=
In[7]:=
Get[file]
Out[7]=

Properties and Relations (4) 

SetDirectory pushes a directory onto the DirectoryStack[]:

In[8]:=
SetDirectory[$InstallationDirectory];
SetDirectory[$TemporaryDirectory];
DirectoryStack[]
Out[8]=

Any changes made to DirectoryStack[] during evaluation of DirectoryBlock[expr] are reverted when evaluation of expr completes:

In[9]:=
ResourceFunction["DirectoryBlock"][SetDirectory[$UserBaseDirectory]; DirectoryStack[]]
Out[9]=

Verify that the original directory stack is restored:

In[10]:=
DirectoryStack[]
Out[10]=

Restore the original working directory:

In[11]:=
ResetDirectory[];
ResetDirectory[]
Out[11]=

Use the resource function ResetDirectoryStack to set the current Directory[] and DirectoryStack[] back to their initial values:

In[12]:=
SetDirectory[$InstallationDirectory];
SetDirectory[$TemporaryDirectory];
DirectoryStack[]
Out[12]=
In[13]:=
ResourceFunction["ResetDirectoryStack"][]
Out[13]=

Verify:

In[14]:=
Directory[] === $InitialDirectory
Out[14]=
In[15]:=
DirectoryStack[] === {}
Out[15]=

DirectoryBlock essentially uses ResetDirectoryStack to restore directory state:

In[16]:=
Module[{dir = Directory[], stack = DirectoryStack[], result},
 result = SetDirectory[$TemporaryDirectory];
 ResourceFunction["ResetDirectoryStack"][dir, stack];
 result
 ]
Out[16]=
In[17]:=
Directory[]
Out[17]=
In[18]:=
DirectoryStack[]
Out[18]=

Change the current working directory:

In[19]:=
SetDirectory[$HomeDirectory]
Out[19]=

Using SetDirectory for both changing to a directory and returning to the original leaves undesirable directories in DirectoryStack[]:

In[20]:=
original = Directory[]
Out[20]=
In[21]:=
temp = CreateDirectory[]
Out[21]=
In[22]:=
SetDirectory[temp];
Put[1, "file.wl"];
SetDirectory[original];

This restores the original directory, but leaves extra paths on the DirectoryStack[]:

In[23]:=
Directory[]
Out[23]=
In[24]:=
DirectoryStack[]
Out[24]=

As a result, ResetDirectory[] will not return to the original location:

In[25]:=
ResetDirectory[]
Out[25]=
In[26]:=
Directory[]
Out[26]=

Completely reset the DirectoryStack[]:

In[27]:=
While[DirectoryStack[] =!= {}, ResetDirectory[]]

Set the current working directory again:

In[28]:=
SetDirectory[$HomeDirectory]
Out[28]=

Now use DirectoryBlock when changing to the temporary directory:

In[29]:=
ResourceFunction["DirectoryBlock"][SetDirectory[temp]; Put[2, "file.wl"]]

Both Directory[] and DirectoryStack[] are restored:

In[30]:=
Directory[]
Out[30]=
In[31]:=
DirectoryStack[]
Out[31]=

This means ResetDirectory[] will work as expected:

In[32]:=
ResetDirectory[]
Out[32]=
In[33]:=
Directory[]
Out[33]=

Version History

  • 1.0.0 – 24 February 2020

Related Resources

License Information