Julia doesn’t use shell like other languages for running external programs. How can I do the equivalent of cd temp_dir && some_cmd
in Julia? As far as I understand cd()
changes the working directory globally which is a problem if I execute blocks of code in parallel.
,
An option which is safe for use with concurrent tasks is setenv(cmd, dir=some_working_dir)
. This will create a Cmd
object which will get some_working_directory
in the child process without interfering with the working directory in your Julia session.
For example,
julia> run(setenv(`ls`, dir="temp_dir"))
code.jl file.txt
Process(setenv(`ls`; dir="temp_dir"), ProcessExited(0))
,
Looking at the docstring for the cd
function:
help?> cd
search: cd Cdouble gcd gcdx secd vecdot asecd cld Cmd codeunit CodeInfo
cd(dir::AbstractString=homedir())
Set the current working directory.
cd(f::Function, dir::AbstractString=homedir())
Temporarily changes the current working directory and applies function f
before returning.
We can use the second method to cd
into a directory, run a command, and then continue execution.
julia> cd(readdir, "temp_dir/")
2-element Array{String,1}:
"code.jl"
"file.txt"
julia> cd("temp_dir/") do
mkdir("subdir")
end
julia> cd(readdir, "temp_dir/")
3-element Array{String,1}:
"code.jl"
"file.txt"
"subdir"
We can pass any function as the first argument, including custom ones (concisely written using a do
block).
,
I figured out a way which makes the shell user happy.
Just write
run(`bash -c """cd temp_dir && some_cmd"""`)
and we are good!
Bonus of this method is that these sub-shells are independent. E.g., I want an external program to generate force field for me, as in a molecular dynamics simulation. I need generate a tone of point-wise data. I would write it in parallel (using Threads
). The cd
function in Julia will somehow change the working directory for all threads while in the solution given above it is thread-safe.