如何在swift中执行终端命令?

时间:2017-03-25 09:14:07

标签: node.js swift bash macos terminal

我是史密斯的新手。如何从Swift代码运行此过程?

  1. 打开终端窗口
  2. 执行cd Desktop/firebase-mac
  3. 执行npm start
  4. 我实际上要做的是从Swift代码点击启动Node服务器。

4 个答案:

答案 0 :(得分:7)

完整示例:

  • 转到某个目录,让我们说Desktop
  • 创建一个名为swsh的文件,并添加到其中(明文,而不是rtf或doc)
#!/usr/bin/env xcrun swift

import Foundation

func shell(launchPath: String, arguments: [String]) -> String {

    let process = Process()
    process.launchPath = launchPath
    process.arguments = arguments

    let pipe = Pipe()
    process.standardOutput = pipe
    process.launch()

    let output_from_command = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: String.Encoding.utf8)!

    // remove the trailing new-line char
    if output_from_command.characters.count > 0 {
        let lastIndex = output_from_command.index(before: output_from_command.endIndex)
        return output_from_command[output_from_command.startIndex ..< lastIndex]
    }
    return output_from_command
}

let output = shell(launchPath: "/bin/date", arguments: [ ])
print(output)

保存,然后:

  • 打开终端
  • 输入cd ~/Desktop
  • 使用chmod 755 swsh
  • 并将您的swift script作为:./swsh
  • 运行

您将获得如下输出:

Sat Mar 25 14:31:39 CET 2017

修改您的swsh并将shell(...行更改为:

let output = shell(launchPath: "/usr/bin/env", arguments: [ "date" ])

运行它并再次获得日期,但现在:

  • swsh执行/usr/bin/env,(带参数date
  • 并且/usr/bin/env找到命令date
  • 并执行它

现在,在~/Desktop中创建另一个文件,并将其命名为from_swift

加入

echo "Today's date is $(date)"

更改文件swsh,将shell行更改为:

let output = shell(launchPath: "./from_swift", arguments: [ ])

注意,./from_swift - 使用.的相对路径(我们位于~/Desktop目录中)。运行swift程序:

./swsh

输出:

2017-03-25 14:42:20.176 swift[48479:638098] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'launch path not accessible'

当然,脚本from_swift 尚未可执行。所以执行:

chmod 755 from_swift
# and run
./swsh

再次出错:

2017-03-25 14:45:38.523 swift[48520:639486] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't posix_spawn: error 8'

这是因为from_swift是一个脚本(不是已编译的二进制文件),因此操作系统需要知道哪个二进制文件应该解释脚本内容。因为这是shell script编辑from_swift脚本:

#!/bin/sh
echo "Today's date is $(date)"

注意添加的&#34; shebang&#34; line:#!/bin/sh。运行swift ./swsh并将获得

Today's date is Sat Mar 25 14:50:23 CET 2017

Horray,你从bash执行了第一个swift脚本。 ;)

当然,您可以使用/usr/bin/env中的shebang,现在更改from_swift的内容,例如:

#!/usr/bin/env perl

use strict;
use utf8;
use English;
binmode STDOUT, ":utf8";

printf "The $EXECUTABLE_NAME (ver:$PERL_VERSION) runs me: $0\n";
printf "I ❤️ perl!\n";

运行./swsh并获得:

The /usr/bin/perl (ver:v5.18.2) runs me: ./from_swift
I ❤️ perl!

注意,我们更改了./swsh文件中的 nothing ,只更改了脚本文件./from_swift

所有上述操作均使用:

$ uname -a
Darwin nox.local 16.4.0 Darwin Kernel Version 16.4.0: Thu Dec 22 22:53:21 PST 2016; root:xnu-3789.41.3~3/RELEASE_X86_64 x86_64
$ swift --version
Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9

因此,很容易创建和执行任何脚本。因此,您可以输入~/Desktop/from_swift

#!/bin/sh
cd $HOME/Desktop/firebase-mac
npm start

可以从swsh开始直接,(Jens Meder建议),但是使用它可以很容易地从给定的脚本文件中执行任何操作。

请记住:process.launch()执行:

  • 已编译的二进制文件
  • 或脚本文件,但脚本文件
    • 必须拥有shebang
    • 并且必须使用chmod 755 /path/to/script.file
    • 执行

答案 1 :(得分:1)

您可以使用以下代码段,例如run("npm start")。它将在默认shell /bin/sh上执行该命令,并将输出作为String返回。

func run(_ cmd: String) -> String? {
    let pipe = Pipe()
    let process = Process()
    process.launchPath = "/bin/sh"
    process.arguments = ["-c", String(format:"%@", cmd)]
    process.standardOutput = pipe
    let fileHandle = pipe.fileHandleForReading
    process.launch()
    return String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8)
}

如果您想使用其他bash,则只需替换launchPath,例如,对于Zsh,它将为/bin/zsh

答案 2 :(得分:0)

要启动传递一个参数的进程,您只需要一行:

Process.launchedProcess(launchPath: "/Users/aharon/Desktop/firebase-mac/npm", arguments: ["start"])

但是如果应用程序是沙盒的话,请考虑文字路径不起作用。

答案 3 :(得分:0)

使用swift-commands

import Commands

Commands.Bash.system("cd /Users/${name}/Desktop/firebase-mac && npm start")