我想执行用户指定的终端命令。例如,用户可能在文本字段中写入killall "TextEdit"
或say "Hello world!"
,而我想执行该命令。
NSTask 是要走的路,除了我有两个问题:
第一:论据。现在我正在这样做:
NSArray* args = [commandString componentsSeparatedByString: @" "];
[task setArguments: [args subarrayWithRange: NSMakeRange(1, [args count] - 1)]]; // First one is the command name
这是这样做的方法吗?我不认为我对此有任何问题,但我看起来并不安全。想象一下:用户写入killall 'Address Book'
但命令接收为参数'Address
和Book'
?? 那是行不通的。那么,我应该怎么做呢?如何安全地解析参数?
第二:发射路径。只需要编写命令的名称而不是完整的路径对用户来说更加友好。所以我想支持这一点,这意味着以编程方式找出只有它的名称的命令的完整路径。为此,我在 NSTask 上写了一个这样的类别:
+ (NSString*)completePathForExec: (NSString*)exec
{
NSTask* task = [[NSTask alloc] init];
NSPipe* pipe = [[NSPipe alloc] init];
NSArray* args = [NSArray arrayWithObject: exec];
[task setLaunchPath: @"/usr/bin/which"];
[task setArguments: args];
[task setStandardOutput: pipe];
[task setStandardError: pipe];
[task launch];
[task waitUntilExit];
NSFileHandle* file = [pipe fileHandleForReading];
NSString* result = [[NSString alloc] initWithData: [file readDataToEndOfFile] encoding: NSASCIIStringEncoding];
if ([result length]) {
if ([result hasSuffix: @"\n"]) { result = [result substringWithRange: NSMakeRange(0, [result length] - 1)]; }
return result;
}
else { return exec; }
}
这似乎运作良好。但是,我如何确定这条路径:/usr/bin/which
将始终有效?我的意思是:它会在 10.6、10.7、10.8 等上运行吗?我想我曾经遇到过一个问题,即 shell 命令的路径随系统版本而变化,你永远不会太小心。
如果保证路径保持不变,那么这不是问题。如果它改变了,那么我怎么知道“路径查找器的路径”?