如何在swift中执行terminal命令?

我是新来的。 我如何从Swift代码运行这个过程?

  1. 打开terminal窗口
  2. 执行cd Desktop/firebase-mac
  3. 执行npm start

我真正想要做的是从Swift代码单击启动节点服务器。

完整的例子:

  • 去一些目录,让说Desktop
  • 创build一个名为swsh的文件,并添加到它(明文,而不是rtf或文档)
 #!/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) 

保存和:

  • 打开terminal
  • 键入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" ]) 

运行它,再次会得到date,但现在:

  • swsh执行/usr/bin/env (带有参数date
  • 并且/usr/bin/envfind命令date
  • 并执行它

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

join它

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

更改文件swshshell行更改为:

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

请注意,./ ./from_swift – 使用相对path. (我们在~/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)" 

注意添加的“shebang”行: #!/bin/sh 。 运行swift ./swsh并得到

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

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

当然,你可以在shebang使用/usr/bin/env ,所以现在把from_swift的内容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文件,只是脚本文件./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 

所以,很容易创build和执行任何脚本。 所以,你可以进入你的~/Desktop/from_swift

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

可以直接swsh中(Jens Meder提出的),但是使用这个方法你可以非常容易地从给定的脚本文件中执行任何操作。

只要记住: process.launch()执行以下任一操作:

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

你可以使用下面的代码片段,例如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,只需要replacelaunchPath ,例如,对于Zsh,它将是/bin/zsh

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

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

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