gpt4 book ai didi

objective-c - 如何在一致的环境中循环使用 NSTask 运行终端命令?

转载 作者:行者123 更新时间:2023-12-01 22:41:07 26 4
gpt4 key购买 nike

我想用 NSTask 来模拟 Terminal 来运行命令。代码如下。它可以循环获取输入并返回过程输出。

int main(int argc, const char * argv[])
{
@autoreleasepool {
while (1) {
char str[80] = {0};
scanf("%s", str);
NSString *cmdstr = [NSString stringWithUTF8String:str];

NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c", cmdstr, nil]];

NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];

[task launch];

NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];

[task waitUntilExit];

NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);

}
}

我的问题是:当一个循环结束后,运行环境恢复到初始化状态。比如默认的运行路径是/Users/apple,我运行cd/把路径改成/,然后运行pwd,它返回/Users/apple而不是/

那么如何使用 NSTask 来完全模拟终端呢?

最佳答案

cdpwd 是 shell 内置命令。如果执行任务

/bin/sh -c "cd /"

无法将更改后的工作目录返回给调用进程。如果要设置变量 MYVAR=myvalue,也会存在同样的问题。

您可以尝试分别解析这些行并更新环境。但是像

这样的多行命令呢?
for file in *.txt
do
echo $file
done

您不能通过将每一行发送到单独的 NSTask 进程来模拟它。

你唯一能做的就是用 NSTask 启动一个单个 /bin/sh 进程,并将所有输入行提供给该过程的标准输入。但是你不能使用 readDataToEndOfFile 来读取输出,但你必须异步读取(使用 [[pipe fileHandleForReading] waitForDataInBackgroundAndNotify])。

简而言之:您只能通过运行(单个)shell 来模拟终端。

已添加:或许您可以将以下内容作为您应用的起点。 (我省略了所有错误检查。)

int main(int argc, const char * argv[])
{
@autoreleasepool {

// Commands are read from standard input:
NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];

NSPipe *inPipe = [NSPipe new]; // pipe for shell input
NSPipe *outPipe = [NSPipe new]; // pipe for shell output

NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setStandardInput:inPipe];
[task setStandardOutput:outPipe];
[task launch];

// Wait for standard input ...
[input waitForDataInBackgroundAndNotify];
// ... and wait for shell output.
[[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];

// Wait asynchronously for standard input.
// The block is executed as soon as some data is available on standard input.
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:input queue:nil
usingBlock:^(NSNotification *note)
{
NSData *inData = [input availableData];
if ([inData length] == 0) {
// EOF on standard input.
[[inPipe fileHandleForWriting] closeFile];
} else {
// Read from standard input and write to shell input pipe.
[[inPipe fileHandleForWriting] writeData:inData];

// Continue waiting for standard input.
[input waitForDataInBackgroundAndNotify];
}
}];

// Wait asynchronously for shell output.
// The block is executed as soon as some data is available on the shell output pipe.
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:[outPipe fileHandleForReading] queue:nil
usingBlock:^(NSNotification *note)
{
// Read from shell output
NSData *outData = [[outPipe fileHandleForReading] availableData];
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
NSLog(@"output: %@", outStr);

// Continue waiting for shell output.
[[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
}];

[task waitUntilExit];

}
return 0;
}

关于objective-c - 如何在一致的环境中循环使用 NSTask 运行终端命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13217415/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com