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))
}
}