执行run(`cd /path/to/foo & sh run.sh`)的时候出错

昨天在写一个build脚本的时候,需要切换到一个build目录里执行cmakemake操作,不过报错了,然后发现其实只要执行run(cd xxx)就会报错:

julia> run(`cd ..`)
ERROR: IOError: could not spawn `cd ..`: no such file or directory (ENOENT)
Stacktrace:
 [1] _jl_spawn(::String, ::Array{String,1}, ::Cmd, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:370
 [2] (::getfield(Base, Symbol("##499#500")){Cmd})(::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:512
 [3] setup_stdio(::getfield(Base, Symbol("##499#500")){Cmd}, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:493
 [4] #_spawn#498(::Nothing, ::Function, ::Cmd, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:511
 [5] _spawn at ./process.jl:507 [inlined]
 [6] #run#509(::Bool, ::Function, ::Cmd) at ./process.jl:669
 [7] run(::Cmd) at ./process.jl:668
 [8] top-level scope at none:0

很奇怪是不是,虽然我知道可以通过cd("xxx")来切换路径,但这会导致current working directory发生改变,导致后面会出现不可预见的问题。

后来我搜了下,没有找到任何相关的信息。

就在要放弃的时候,去文档看了下cd函数,碰巧居然还有这么个实现:

  cd(f::Function, dir::AbstractString=homedir())

  Temporarily change the current working directory to dir, apply function f and finally return to
  the original directory.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> pwd()
  "/home/JuliaUser"
  
  julia> cd(readdir, "/home/JuliaUser/Projects/julia")
  34-element Array{String,1}:
   ".circleci"
   ".freebsdci.sh"
   ".git"
   ".gitattributes"
   ".github"
   ⋮
   "test"
   "ui"
   "usr"
   "usr-staging"
  
  julia> pwd()
  "/home/JuliaUser"

噢,完美解决了我的问题。

but,不知道有没有人知道,run中的command的实现机制是什么?为什么单独对cd的command做了过滤(或许还有其它的我没发现)?

实际上在shell mode里面都不可以 ls * 我觉得这是个问题

我感觉这个行为才是正常的,run(command)cd()和在shell里执行cd的结果应该是一致的。如果我们用上述任何方法切换路径,那么之后的命令都应该在新路径下执行,除非我们再用cd切换回来。

julia> pwd()
"/Users/gnimuc"

shell> pwd
/Users/gnimuc

shell> cd ..
/Users

julia> pwd()
"/Users"

shell> cd gnimuc/
/Users/gnimuc

julia> cd("..")

shell> pwd
/Users

julia> pwd()
"/Users"