【问题标题】:Exit from Command prompt after running r script运行 r 脚本后退出命令提示符
【发布时间】:2018-12-13 11:01:06
【问题描述】:

我正在通过命令提示符(CMD 窗口)运行一个 R 脚本,但在执行所有批处理命令后 CMD 窗口保持打开状态。我想在执行 R 脚本后关闭它(CMD 窗口)。

@ECHO OFF
START cmd.exe /k "cd C:\ABCD\" & Rscript working.r & exit

我正在运行上面的代码,但最后一个命令 exit 对我不起作用。

我在上面的代码中遗漏了什么吗?

【问题讨论】:

  • 您应该考虑使用 START 命令的 /D 选项来设置工作目录。

标签: r batch-file


【解决方案1】:
  • 你只有双引号cd C:\ABCD;您必须将整个命令序列双引号。
  • 使用&& 运算符,因此如果路径C:\ABCD 不存在,您的脚本将失败。
  • 如果你想在完成给定的命令后终止 cmd,你应该使用/c 选项。以下是我的建议:

使用cmd /k选项(运行,然后返回到cmd提示符):

start cmd.exe /k "cd /d C:\ABCD\ && Rscript working.r & exit"

使用cmd /c 选项(运行命令,然后终止):

start cmd.exe /c "cd /d C:\ABCD\ && Rscript working.r"

文件名中的单词最好用_- 符号(下划线或破折号)或大写字母(驼峰式)连接。

cd/d 选项用于更改驱动器(如果需要)。

参考:CMD.exe on SS64

【讨论】:

    【解决方案2】:

    1。 Windows 命令处理器选项/k 的含义

    Windows 命令处理器选项/K 用于运行命令行,然后keeps 运行Windows 命令处理器cmd.exe 以供用户交互使用或仅查看执行的输出命令行。

    /C 选项用于运行命令行,然后 Windows 命令处理器 c会丢失自身,这意味着带有输出的控制台窗口也将关闭。

    cmd.exe 的使用帮助解释了这一点,可以通过打开command prompt 并运行cmd /? 来阅读。还有cmd 的 Microsoft 文档页面解释了这两个选项。

    2。 Windows 命令处理器运算符& 的含义

    single line with multiple commands using Windows batch file 详细解释了无条件命令运算符 & 以及条件命令运算符 &&|| 在双引号参数字符串之外被 Windows 命令处理器识别。

    无条件命令运算符&用于指定一个命令行上的多个命令,由cmd.exe一个接一个地执行,而与前一个执行命令的成功或失败无关。

    所以命令行

    START cmd.exe /k "cd C:\ABCD\" & Rscript working.r & exit
    

    cmd.exe 解释处理批处理文件,因为它将写入批处理文件:

    START cmd.exe /k "cd C:\ABCD\"
    Rscript working.r
    exit
    

    批处理文件的目标是将当前目录更改为C:\ABCD\,使用参数Rscript.exe 运行working.r 以处理目录C:\ABCD\ 中的此R 脚本,并保持控制台窗口打开以查看启动批处理文件时打开的控制台窗口的输出应在启动Rscript.exe 后自动关闭。但是使用的命令行完全不同,下面第 5 章会详细说明。

    3。在C:\ABCD 中运行R 脚本working.r 的解决方案

    C:\ABCD 目录中运行 R 脚本 working.r 并保持控制台窗口打开并显示 R 脚本的输出的目标可以通过以下方式实现:

    @echo off
    title Run R script working.r
    cd /D "C:\ABCD\"
    if not errorlevel 1 Rscript.exe working.r
    pause
    

    这些命令行执行以下操作:

    1. CMD 内部命令 ECHO 用于关闭命令回显模式,该模式在执行批处理文件时默认启用,从而显示要在之后执行的命令行在执行之前立即对其进行解析和处理。
      @ 在此行的开头会导致在处理之后和执行之前不将批处理文件的第一个命令行打印到控制台窗口。
    2. CMD 内部命令 CD 使用选项 /D 将正在运行的 Windows 命令进程的当前目录更改为指定目录,以更改当前驱动器,如果也是必须的。
      这适用于所有以驱动器号和冒号开头的目录路径,但不适用于以 \\ServerName\ShareName\ 开头的 UNC 路径,因为 cmd.exe 默认情况下不允许使用 UNC 路径访问的目录作为当前目录与不支持当前目录这样的目录路径的可执行文件兼容。
    3. 如果命令 CD 的执行成功且退出值为 0,Windows 命令处理器会在当前目录和环境中列出的目录中搜索名称为 Rscript.exe 的文件变量PATH 使用环境变量PATHEXT 中列出的文件扩展名,如果确实找到该文件,则使用其完全限定的文件名(驱动器+路径+名称+扩展名)运行Rscript.exe,并将working.r作为参数传递给可执行文件。
      搜索Rscript.exe 及其在CD 上的执行没有完成,值1 表示错误,例如,如果目录C:\ABCD 在此期间被删除。 CD 在这种情况下输出一条错误消息来处理 STDERR(标准错误),可以在控制台窗口中看到。
    4. 命令 PAUSE 会暂停批处理文件的处理,直到用户按下任意键,这样即使已开始执行批处理文件,用户也可以查看写入控制台窗口的所有输出通过在 Windows 文件资源管理器中双击它。

    要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

    • cd /?
    • echo /?
    • if /?
    • pause /?
    • title /?

    另见:

    还有多种其他可能的解决方案。

    上述的较短版本:

    @echo off
    title Run R script working.r
    cd /D "C:\ABCD\" && Rscript.exe working.r
    pause
    

    另一种单行解决方案,启动一个命令处理器:

    @start "Run R script working.r" /D "C:\ABCD" %ComSpec% /D /K Rscript.exe working.r
    

    这个单一的命令行结果

    • 使用 system 环境变量 ComSpec 定义的完全限定文件名启动 Windows 命令处理器 cmd.exe
    • 使用选项 /D 忽略 Windows 注册表中的 AutoRun 命令(如果存在)并且
    • 使用选项 /K,如第 1 章所述
    • 作为新控制台窗口中的单独任务,窗口标题为Run R script working.r
    • C:\ABCD 作为启动cmd.exe 的当前目录
    • 搜索文件Rscript.exe,如果找到,使用R 脚本文件名working.r 作为第一个也是唯一的参数执行它,当前目录C:\ABCD 定义为cmd.exe

    有关命令START的帮助,请在命令提示符窗口start /?中运行。

    另一种单行解决方案是:

    @start "Run R script working.r" /D "C:\ABCD" %SystemRoot%\System32\cmd.exe /D /K Rscript.exe working.r
    

    这与上面的单个命令行版本相同,只是使用%SystemRoot%\System32\cmd.exe 而不是%ComSpec% 的细微差别实际上默认情况下使用该字符串完全定义为system环境变量。

    最后但同样重要的是也可以使用单个命令行:

    @start "Run R script working.r" %SystemRoot%\System32\cmd.exe /D /S /K "cd /D "C:\ABCD" && Rscript.exe working.r"
    

    如果文件working.r 的目录路径本身包含字符&,则此解决方案将成为一场噩梦,因为在这种情况下,目录路径中的& 符号必须用^ 转义到&,因为命令行是由两个cmd.exe 处理。处理批处理文件的cmd.exe 实例必须将命令行上的所有& 符号解释为文字字符,而目录路径中的& 必须解释为文字字符,&& 必须解释为条件 AND 运算符通过第二个cmd.exe

    在目录路径中使用& 的最后一个解决方案示例:

    @start "Run R script working.r" %SystemRoot%\System32\cmd.exe /D /S /K "cd /D "C:\Temp\Development ^& Test" && Rscript.exe working.r"
    

    这比:

    @start "Run R script working.r" /D "C:\Temp\Development & Test" %SystemRoot%\System32\cmd.exe /D /K Rscript.exe working.r
    

    4。根本不使用批处理文件的替代解决方案

    执行像Rscript.exe 这样的可执行文件,在用作当前目录的特定目录中使用一个或多个参数,并使用Windows 命令处理器查看输出,也可以使用Windows .lnk 快捷方式文件而不是与批处理文件解决方案相比,具有多个优点的批处理文件。

    可以使用以下步骤在目录C:\ABCD中创建以working.r为参数执行Rscript.exe的快捷方式文件:

    1. Windows 文件资源管理器中浏览到包含cmd.exe(通常为C:\Windows\System32)的Windows 目录中的System32 目录。
    2. 在文件cmd.exe 上单击辅助(右)指点设备(鼠标)按钮以打开上下文菜单并单击菜单项桌面上的子菜单发送到(创建快捷方式)
    3. 切换到 Windows 桌面,现在有一个名为 cmd.exe.lnk 的附加快捷方式文件,其中文件扩展名 .lnk 不可见,只有文件名 cmd.exe
    4. cmd.exe 上单击辅助(右)指点设备(鼠标)按钮,然后单击菜单项重命名 上打开的上下文菜单以将文件名更改为例如Run R Script,从而生成快捷方式文件被重命名为Run R Script.lnk
    5. Run R Script 上单击辅助(右)定点设备(鼠标)按钮,然后在最后一个菜单项属性上单击打开的上下文菜单。
    6. 属性对话框窗口打开,默认选择标签快捷方式。在此选项卡上,必须首先修改属性 Target,在其上附加空格字符和字符串 /D /K Rscript.exe working.r。好吧,更好的办法是在空格后面附加字符串/D /K "C:\Full Path\Rscript\Rscript.exe" working.r,这样cmd.exe 就不需要使用环境变量PATHPATHEXT 来搜索文件Rscript.exe
    7. 接下来必须修改属性Start in,其中必须输入C:\ABCD,因为该目录应该是当前目录,首先是cmd.exe,然后是下一个Rscript.exe,因为包含 R 脚本文件working.rStart in 目录路径的定义应始终不带双引号,即使包含空格或其中一个字符 &()[]{}^=;!'+,`~,因为该字符串未由开始的 cmd.exe 处理,如下面第 5 章所述.

    也可以修改快捷方式文件的其他属性。可以定义一个 快捷键Ctrl + Alt + R 来执行 R 脚本 working.r in C:\ABCD 通过按下这个独立于哪个键的组合应用程序当前具有输入焦点。当定点设备指针位于 Windows 桌面上的快捷方式上时,可以添加类似Run R script working.r in C:\ABCD评论,显示为工具提示。可以为此快捷方式选择一个漂亮的图标,并可以设置不同的字体或字体大小等。

    最后一步是点击按钮OK保存更改的快捷方式属性。

    快捷方式文件可以保存在 Windows 桌面上,但也可以移动或复制到 Windows 开始菜单或固定在 Windows 任务栏上,因为它可以使用任何快捷方式文件完成。

    因此,使用快捷方式文件可以简化 R 脚本的执行,尤其是在定义了快捷键的情况下。可以更改字体和字体大小以查看比通常在命令提示符窗口中更大的输出。当 R 脚本运行时,可以在 Windows 任务栏中选择一个漂亮的图标,等等。

    5。问题中发布的批处理文件是如何处理的?

    问题中发布的批处理文件很可能是通过双击它来执行的。因此,explorer.exe 很可能是处理批处理文件的第一个可执行文件。

    5.1 explorer.exe对批处理文件的处理

    文件扩展名为.bat.cmd 的批处理文件是一个文本文件,它本身不包含CPU 指令。因此 Windows 文件资源管理器 必须首先找出如何处理双击的批处理文件。因此,它会在 Windows 注册表中的各种键下搜索如何打开文件扩展名为 .bat.cmd 的文件,具体取决于批处理文件的文件扩展名。

    1. Windows 文件资源管理器 使用 REG_SZ 类型的默认字符串 batfile 找到键 HKEY_CLASSES_ROOT\.bat
    2. 接下来查找注册表项HKEY_CLASSES_ROOT\batfile\shell\open\command,默认字符串"%1" %* 类型为REG_SZ
      批处理文件的注册方式与其他文件扩展名不同。通常为文件扩展名的 Windows shell 命令 open 配置可执行文件的完全限定文件名,以使用 %1 作为双引号括起来的双击文件的完全限定名的占位符引号。
      .txt 文件扩展名的示例:HKEY_CLASSES_ROOT\.txt 具有默认字符串 txtfile,因此引用 HKEY_CLASSES_ROOT\txtfile\shell\open\command 与默认字符串 %SystemRoot%\system32\notepad.exe %1 类型为 REG_EXPAND_SZ 而不是 REG_SZ 包含环境变量引用。李>

    上面的注册表访问顺序非常简化,否则列出explorer.exe 进行的所有注册表访问以找出如何处理双击的批处理文件真的太长了。

    最后由explorer.exe调用Windows库函数CreateProcess。这个函数有多个参数,任何在 Windows 上工作的程序员都值得阅读这个函数和结构 STARTUPINFO 的文档。

    快捷方式文件的大部分属性只是定义CreateProcess如何被explorer.exe调用结构STARTUPINFO中的哪个数据集。

    CMD 内部命令START 支持的大多数选项只是定义要通过cmd.exe 传递给CreateProcess 的数据。

    一些例子:

    • 函数参数lpCurrentDirectory 是一个长指针,指向一个带有当前目录的字符串,为要创建的进程设置。如果该指针是空指针,CreateProcess 使用创建新进程的进程的当前目录。否则,指定的字符串被解释为新进程的当前目录的路径。快捷方式属性Start inexplorer.exe 使用lpCurrentDirectory 传递给函数CreateProcess 的字符串。 CMD 的命令START 的选项/D 之后的字符串是cmd.exe 使用lpCurrentDirectory 传递给函数CreateProcess 的不带双引号的字符串。李>
    • 结构STARTUPINFO 具有元素dwFlags,它是一个位域,其中一位为STARTF_USESHOWWINDOWcmd.exe 运行 Windows 控制台应用程序,例如在批处理文件中指定的 Rscript.exe 默认情况下使用 CreateProcessSTARTUPINFO 中的 dwFlags 中的此位 STARTUPINFO 传递一个指向 CreateProcess 的指针,其值为 0。所以在运行Rscript.exe 时不会打开新的控制台窗口。但是在使用命令 START 时,标志 STARTF_USESHOWWINDOW 始终具有 CreateProcess 上的值 1cmd.exe 调用以始终使用新窗口运行应用程序。 explorer.exe 始终设置为 STARTF_USESHOWWINDOW
    • 结构STARTUPINFO 具有hStdInputhStdOutputhStdError 元素,它们由cmd.exe 定义,具体取决于Rscript 等控制台应用程序应该使用标准输入、标准输出和标准错误流cmd.exe 或新的流应该由 CreateProcess 为这个应用程序创建,这是直接从批处理文件中运行 Rscript.exe 或使用命令 START 之间的另一个区别。

    每个能够再运行一个 Windows 可执行文件的 Windows 可执行文件调用 Windows 内核库 kernel32.dll 中的 CreateProcss。因此,对于每个 Windows 程序员来说,了解这个函数、可以将哪些数据传递给它以及它是如何工作的,这真的很有用。

    所以最后explorer.exe使用CreateProcess运行,例如:

    C:\Windows\System32\cmd.exe /c ""C:\Users\UserName\Desktop\RunRscript.bat" "
    

    CreateProcessexplorer.exe 的要求打开一个新的控制台窗口,默认情况下使用存储在注册表项HKEY_CURRENT_USER\Console 下的选项在启动cmd.exe 时使用选项/c 处理双击的批处理文件然后自行关闭。

    5.2 cmd.exe对批处理文件的处理

    Windows 命令处理器首先解析explorer.exe 传递给它的参数字符串,它们是/c 和包含在" 中的要执行的命令行,其中第一个和最后一个" 被删除,最后只有用双引号括起来的批处理文件的完全限定文件名。

    出于这个原因,Windows 命令处理器打开批处理文件,读取第一行,解析它,发现不必再读取任何行,关闭批处理文件并执行第一个命令行 @ECHO OFF 导致关闭命令回显模式。

    接下来cmd.exe 再次打开批处理文件,将文件指针设置为第二行的开头,读取该行,解析它,发现不再需要读取行,关闭批处理文件并在内部拆分命令线

    START cmd.exe /k "cd C:\ABCD\" & Rscript working.r & exit
    

    将以下命令添加到其内部命令队列中:

    START cmd.exe /k "cd C:\ABCD\"
    Rscript working.r
    exit
    

    所以接下来要执行三个命令,独立于前一个命令的执行结果。

    5.2.1 再启动一个cmd.exe 作为单独的任务

    要执行的第一个命令是内部命令START。所以cmd.exe 会按照 START 命令的描述解析参数。

    既没有定义窗口标题字符串,也没有定义任何其他 START 特定选项。所以第一个参数cmd.exe 是传递给CreateProcess 的应用程序名称。但是路径丢失了,因此cmd.exe处理批处理文件必须首先搜索这个文件。

    当前目录中很可能没有cmd.exe。因此,接下来使用环境变量PATH 中的第一个文件夹路径来搜索cmd.exe。 Windows 默认是%SystemRoot%\System32 作为PATH 的第一个文件夹路径,这个目录确实包含cmd.exe。这样就可以快速完成对cmd.exe全限定文件名的搜索,并且通过函数参数lpApplicationName传递给函数CreateProcess的应用程序名称字符串被完整定义。

    cmd.exe 之后的所有其他参数都将使用指针lpCommandLine 作为字符串传递给CreateProcess

    因此,处理批处理文件的cmd.exe 现在调用CreateProcessC:\Windows\System32\cmd.exe 作为应用程序名称,字符串/k "cd C:\ABCD\" 作为命令行,当前目录的空指针,环境的空指针等。再启动一个cmd.exe 与当前cmd.exe 进程并行运行,具有自己的控制台窗口和自己的标准输入、标准输出和标准错误流。

    处理批处理文件的cmd.exe 进程从CreateProcess 返回一个非零值以成功创建该进程。因此,它继续执行其内部命令队列中的下一个命令,而启动的 cmd.exe 现在正在并行运行。

    5.2.2 使用参数working.r 调用Rscript

    cmd.exe处理批处理文件的内部命令队列中的下一条命令是:

    Rscript working.r
    

    Rscript 不是 CMD 的内部命令。因此,这个字符串被解释为可执行文件或脚本文件名,必须首先找到它,仅使用没有完整路径和文件扩展名的文件名指定。因此cmd.exe 再次使用环境变量PATHPATHEXT 来查找具有该名称的程序/脚本文件,并且很可能确实在正确的目录中找到Rscript.exe

    再次调用CreateProcess,但这次应用程序名称为Rscript.exe及其完整路径,命令行为字符串working.rlpEnvironment又是一个空指针(与往常一起使用) cmd.exe 的空指针),lpCurrentDirectory 是空指针等。不同之处在于这次 Rscript.exe 不是作为具有自己的窗口、标准流等的单独任务启动的。Rscriptcmd.exe调用

    因此Rscript.exe 现在运行并处理命令行。如果根本找不到文件working.r,则无法通过问题中提供的信息来确定。如果 R 脚本文件与批处理文件位于同一目录中,则继承由 explorer.exe 定义的当前工作目录,从 cmd.exe 开始处理批处理文件,cmd.exe 在开始 Rscript.exe 时处理 R脚本文件现在偶然导致 R 脚本文件的工作执行。否则Rscript.exe 很可能退出并出现错误,因为在当前目录中找不到文件working.r

    Rscript.exe 不执行或不执行working.r 完成后,处理批处理文件的Windows 命令处理器实例继续使用其内部命令队列。

    5.2.3 退出 Windows 命令处理器

    内部命令队列中剩余的命令是exit,它是CMD的内部命令。它指示立即退出而不进一步处理批处理文件。所以cmd.exe 处理批处理文件现在会自行关闭。

    5.3 处理第二次启动cmd.exe

    cmd.exe 处理批处理文件启动的cmd.exe 进程首先处理它的参数。

    有选项/k 指示cmd.exe 执行下一个参数指定的命令行,然后继续运行。

    要执行的命令行是cd C:\ABCD\,其中CD被识别为CMD的内部命令,C:\ABCD\为目录路径。

    命令CD被执行,如果当前驱动器是驱动器C:,当前目录现在更改为第二个cmd.exe进程,而第一个cmd.exe进程正在并行搜索为Rscript.exe

    第二个 cmd.exe 没有什么可做的,但它会继续运行以进行用户交互。

    第二个cmd.exe 的控制台窗口保持打开状态,提示指示C:\ABCD 为当前目录并等待用户输入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 2015-10-21
      • 2010-10-05
      相关资源
      最近更新 更多