Execute a terminal command from a Cocoa app

后端 未结 12 2319
既然无缘
既然无缘 2020-11-22 06:34

How can I execute a terminal command (like grep) from my Objective-C Cocoa application?

12条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-22 06:48

    Objective-C (see below for Swift)

    Cleaned up the code in the top answer to make it more readable, less redundant, added the benefits of the one-line method and made into an NSString category

    @interface NSString (ShellExecution)
    - (NSString*)runAsCommand;
    @end
    

    Implementation:

    @implementation NSString (ShellExecution)
    
    - (NSString*)runAsCommand {
        NSPipe* pipe = [NSPipe pipe];
    
        NSTask* task = [[NSTask alloc] init];
        [task setLaunchPath: @"/bin/sh"];
        [task setArguments:@[@"-c", [NSString stringWithFormat:@"%@", self]]];
        [task setStandardOutput:pipe];
    
        NSFileHandle* file = [pipe fileHandleForReading];
        [task launch];
    
        return [[NSString alloc] initWithData:[file readDataToEndOfFile] encoding:NSUTF8StringEncoding];
    }
    
    @end
    

    Usage:

    NSString* output = [@"echo hello" runAsCommand];
    

    And if you're having problems with output encoding:

    // Had problems with `lsof` output and Japanese-named files, this fixed it
    NSString* output = [@"export LANG=en_US.UTF-8;echo hello" runAsCommand];
    

    Hope it's as useful to you as it will be to future me. (Hi, you!)


    Swift 4

    Here's a Swift example making use of Pipe, Process, and String

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

    Usage:

    let output = "echo hello".run()
    

提交回复
热议问题