0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftからPOSIXコマンドを呼び出す

Last updated at Posted at 2021-06-23

概要

参考

実装

呼び出し元クラス

  • エラー有無と出力文字列の両方が欲しいので、返り値にResult<Success, Failure>を使用する
import Foundation


enum ExecutingCommandError: Error {
    case errorStatus(status: Int32, commandResult: CommandResult)
}

struct CommandResult {
    let command: String
    let standardOutputMessage: String?
    let standardErrorMessage: String?
    
    var description: String {
        var message = "【Command】\n" + "\(command)\n"
        if let standardOutputMessage = standardOutputMessage,
           !standardOutputMessage.isEmpty {
            message += "(Standard Output)\n" + standardOutputMessage
        }
        
        if let standardErrorMessage = standardErrorMessage,
           !standardErrorMessage.isEmpty {
            message += "(Standard Error)\n" + standardErrorMessage
        }
        
        return message
    }
}


func executeCommand(command: String, currentDirectoryURL: URL?) -> Result<CommandResult, ExecutingCommandError> {
    let process = Process()
    process.launchPath = "/bin/bash"  // ワイルドカードを展開するためbashを経由する
    process.arguments = ["-c", command]
    
    let outputPipe = Pipe()
    let errorPipe = Pipe()
    process.standardOutput = outputPipe
    process.standardError = errorPipe
    process.currentDirectoryURL = currentDirectoryURL
    process.launch()
    process.waitUntilExit()
    
    while process.isRunning {
        Thread.sleep(forTimeInterval: 1.0)
    }
    
    let outputMessage = String(data: outputPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
    let errorMessage = String(data: errorPipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)
    let commandResult = CommandResult(command: command,
                                      standardOutputMessage: outputMessage,
                                      standardErrorMessage: errorMessage)
    
    let status = process.terminationStatus
    if status == 0 {
        return .success(commandResult)
    } else {
        return .failure(.errorStatus(status: status, commandResult: commandResult))
    }
}

呼び出し例

let result = executeCommand(command: "ls -la", currentDirectoryURL: Bundle.main.bundleURL)
switch result {
case .success(let commandResult):
    print(commandResult.description)
case .failure(let error):
    switch error {
    case .errorStatus(status: _, commandResult: let commandResult):
        print(commandResult.description)
    }
}
  • 実行結果は以下の通り
【Command】
ls -la
(Standard Output)
total 0
drwxr-xr-x  3 xxxxx  staff   96 Jun 17 14:10 .
drwxr-xr-x@ 8 xxxxx  staff  256 Jun 23 17:21 ..
drwxr-xr-x  7 xxxxx  staff  224 Jun 17 14:10 Contents
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?