Julia 可以在 REPL 中执行 Shell 命令,就是先输入 ;
进入 shell 模式,然后输入命令就能执行对应的命令。这个操作在 macOS 和 Linux 下都没什么问题。就是 windows 下大家就会出现奇怪的错误。
以下演示均在 Julia 1.0.5(LTS)版本中运行。操作系统为 Windows 10。
shell 模式
图中提示符为绿色的 julia>
时为正常的 REPL 模式,提示符变成红色的 shell>
时则进入了 shell 模式。
一些命令,如图中的 whoami
能正常执行并返回;另一些,如 dir
则报错
ERROR: IOError: could not spawn `dir`: no such file or directory (ENOENT)
中文社区中相关的讨论
- 在 REPL 中使用 shell 报错 - 综合讨论区
- 执行 run(
cd /path/to/foo & sh run.sh
) 的时候出错 - 综合讨论区 / Julia入门 - shell 使用求助 - 综合讨论区
- shell 无法运行任何外部命令,包括echo cd…等等,只能认出直接的文件名路径,这是什么原因呀 - 综合讨论区 / Julia入门
下面简单说明一下这个问题的原因以及解决办法(workaround)。
发生错误的原因
julia 的 shell 模式不是在执行命令,而是在调用外部程序。
命令从不会在 shell 中运行。相反地,Julia 会直接解析命令语法,适当地插入变量并像 shell 那样拆分单词,同时遵从 shell 的引用语法。命令会作为
julia
的直接子进程运行,使用fork
和exec
调用。
—— 运行外部程序 · Julia中文文档
前面使用的 dir
是 cmd 的内部指令(Internal commands),这种命令会被 cmd 捕获,然后执行相应的操作,并没有一个程序叫做 dir.exe
放在硬盘上,如果有那一定可以成功调用。
与之相对的外部命令(External commands)有对应的 exe
文件可供调用,所以能在 shell 模式中成功执行。cmd 外部命令的 exe
文件通常放在 C:\WINDOWS\System32
文件夹中,这个文件夹是 PATH
环境变量的一部分,所以无需输入完整路径即可执行命令。
内部命令列表
ref: Internal commands | SS64.com;An A-Z Index of Windows CMD commands | SS64.com
ASSOC,
BREAK,
CALL ,CD/CHDIR, CLS, COLOR, COPY,
DATE, DEL, DIR, DPATH,
ECHO, ENDLOCAL, ERASE, EXIT,
FOR, FTYPE,
GOTO,
IF,
KEYS,
MD/MKDIR, MKLINK (vista and above), MOVE,
PATH, PAUSE, POPD, PROMPT, PUSHD,
REM, REN/RENAME, RD/RMDIR,
SET, SETLOCAL, SHIFT, START,
TIME, TITLE, TYPE,
VER, VERIFY, VOL
解决办法
tl; dr / 太长不看
;cmd /c dir
。显式的让cmd.exe
执行所需的命令。readdir() # Base.Filesystem
使用内置函数。文件系统 · Julia中文文档- 在 git bash(MSYS2)中启动 Julia。(WSL 目前不行)
调用 cmd.exe
ref: #33924;
内部命令不能直接在 shell 模式中使用,但可以通过 cmd.exe
中转间接使用。
简单粗暴的方式是调用 cmd.exe
,然后把要执行的命令当作参数传递给他(cmd /c
),只要小心转义相关的问题,这个方法还是比较稳妥的。
例子
;cmd /c dir
使用 Base.Filesystem
完成所需的操作
Base.Filesystem
将一些命令行常用操作封装成了 julia 的函数,如果是执行一些简单的操作,直接调用函数就好了。
例子
Base.Filesystem
中的函数无需导入即可使用
julia> pwd()
"C:\\Users\\woclass\\AppData\\Local\\Julia-1.0.5"
julia> readdir() # 等价于 dir
8-element Array{String,1}:
"bin"
"etc"
"include"
"julia.lnk"
"lib"
"LICENSE.md"
"share"
"Uninstall.exe"
Base.Filesystem
中有哪些函数可以看文档 文件系统 · Julia中文文档
或者参考以下列表
以下输出通过在 REPL 中输入
Base.Filesystem.
(最后有一个点),然后按两次tab
键触发自动补全而得到。
输出中全小写的才是函数,其他的是一些宏、类型和常量
julia> VERSION
v"1.0.5"
julia> Base.Filesystem.
@stat_call S_IRWXO eval longpath relpath
AbstractFile S_IRWXU expanduser lstat rename
File S_IWGRP filemode mkdir rm
JL_DUMMY S_IWOTH filesize mkpath samefile
JL_O_APPEND S_IWUSR futime mktemp sendfile
JL_O_CREAT S_IXGRP gperm mktempdir splitdir
JL_O_EXCL S_IXOTH homedir mtime splitdrive
JL_O_NOCTTY S_IXUSR include mv splitext
JL_O_RANDOM StatStruct isabspath normpath stat
JL_O_RDONLY UV_FS_SYMLINK_JUNCTION isblockdev open symlink
JL_O_RDWR _win_tempname ischardev operm temp_prefix
JL_O_SEQUENTIAL abspath isdir path_absolute_re tempdir
JL_O_SHORT_LIVED basename isdirpath path_dir_splitter tempname
JL_O_TEMPORARY cd isfifo path_directory_re touch
JL_O_TRUNC checkfor_mv_cp_cptree isfile path_ext_splitter truncate
JL_O_WRONLY checkmode islink path_separator unlink
SEEK_CUR chmod ismount path_separator_re uperm
SEEK_END chown ispath pathsep uv_dirent_t
SEEK_SET contractuser issetgid pwd walkdir
S_IRGRP cp issetuid readbytes! write
S_IROTH cptree issocket readdir
S_IRUSR ctime issticky readlink
S_IRWXG dirname joinpath realpath
在 git bash 中启动 julia
All of this weirdness on Windows could be addressed by bundling git bash with Julia to handle the shell mode. —— PetrKryslUCSD #23597
git bash 提供了一个 MSYS2 的环境。
MSYS2 是用于辅助 Windows 版 MinGW 进行命令行开发的配套软件包,提供了部分 Unix 工具。
所以它既支持 windows 的 dir
也支持 posix 标准的 ls
。使用它启动 julia,shell 就变成了 git bash 这样就减少了很多的问题。
如果安装了 Git for Windows+git bash 这样用 julia 还是很方便的。
git bash
WSL
参考资料&相关的链接
外部链接
cmd 命令列表
- Windows Commands | Microsoft Docs
- An A-Z Index of Windows CMD commands | SS64.com
- Internal commands - Windows CMD - SS64.com
相关的 issue
- cannot shell out to cmd’s builtin commands · Issue #6316
可能是最早提出这个问题的 issue - start is a cmd builtin, doesn’t work for edit · Issue #7107
- bundle Julia with a better terminal on Windows? · Issue #7267
- Use PowerShell for REPL shell mode on Windows · Issue #16565
- The “shell mode” in the REPL is not fully functional on Windows · Issue #23597
相关的 pr
- Add note for non-Posix and Windows users. by venuur · Pull Request #33924
想要在文档中添加以下说明。
如果短时间内不合并其他的 pr,这个就是目前的最优解。可以去点个赞。!!! note The following assumes a Posix environment as on Linux or MacOS. On Windows, many similar commands, such as `echo` and `dir`, are not external programs and instead are built into the shell `cmd.exe` itself. One option to run these commands is to invoke `cmd.exe`, for example `cmd /C echo hello`. Alternatively Julia can be run inside a Posix environment such as Cygwin.
- REPL shell mode for Windows by musm · Pull Request #33474
- REPL shell mode for Windows by musm · Pull Request #33427
取代 #31490 - REPL shell mode for Windows by stevengj · Pull Request #31490
基于 #23703 和 #21294 的更新、简化版本 - REPL shell mode for Windows by GregPlowman · Pull Request #23703
代替 #21294 - REPL shell mode for Windows by GregPlowman · Pull Request #21294
代替 #20776 - Allow Windows users to specify JULIA_SHELL for REPL shell mode by GregPlowman · Pull Request #20776
此 pr 因为同步时手滑而变得十分混乱,所以关闭了。 - Allow built-in commands in shell mode for Windows by ncnc · Pull Request #11478
英文 discourse 论坛
- Dir does not work in the console? - Usage - JuliaLang
- Newbi First Steps in Julia for Windows - Usage / First steps - JuliaLang
- Dir failing in shell mode (Win, 1.0) - Usage - JuliaLang
Stack Overflow