如何在swift中执行terminal命令?
我是新来的。 我如何从Swift代码运行这个过程?
- 打开terminal窗口
- 执行
cd Desktop/firebase-mac
- 执行
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/env
find命令date
- 并执行它
现在,在~/Desktop
创build另一个文件,并将其命名为from_swift
。
join它
echo "Today's date is $(date)"
更改文件swsh
将shell
行更改为:
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不起作用。