我有一个程序,可以使用FileMerge
比较2个文件。
这确实有效,但偶尔会失败。我怀疑这是因为参数包含空格字符而传递的路径。
以下代码片段构造任务并启动它。
NSTask *task = [[NSTask alloc] init];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
[task setStandardInput:[NSPipe pipe]]; //The magic line that keeps your log where it belongs
NSFileHandle *file = [pipe fileHandleForReading];
[task setLaunchPath: @"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:
@"-c" ,
[[NSUserDefaults standardUserDefaults] stringForKey:PREF_COMPARE_COMMAND],
@"Compare", // $0 place holder
source,
target,
nil];
[task setArguments:arguments];
[task setEnvironment:[NSDictionary dictionaryWithObject:@"/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin" forKey:@"PATH"]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pipeReadCompletionNotification:)
name:NSFileHandleReadCompletionNotification
object:file];
[file readInBackgroundAndNotify];
[task launch];
我尝试了很多选项来尝试转义空格或用引号括起路径,但没有成功。我欢迎任何建议。
作为运行结果的典型参数是: -
"-c",
"opendiff $1 $2",
Compare,
"/Users/ian/temp/Indian Pacific/RailRes Travel Documentation1.pdf",
"/Users/ian/temp/Indian Pacific/RailRes Travel Documentation.pdf"
我试过了
[source stringByReplacingOccurrencesOfString:@" " withString:@"\\ "],
[source stringByReplacingOccurrencesOfString:@" " withString:@"\ "],
第一个实际插入\\
第二个产生编译错误unknown escape sequence
我尝试了Ken Thomases的建议(知道我的名字没有'
)
[[@"'" stringByAppendingString:source] stringByAppendingString:@"'"],
[[@"'" stringByAppendingString:target] stringByAppendingString:@"'"],
不幸的是,这导致了争论
"-c",
"opendiff $1 $2",
Compare,
"'/Users/ian/temp/Indian Pacific/RailRes Travel Documentation1.pdf'",
"'/Users/ian/temp/Indian Pacific/RailRes Travel Documentation.pdf'"
并以同样的方式失败。 /Users/ian/temp/Indian does not exist
编辑_______________________工作守则_____________________________________
NSArray *arguments = [NSArray arrayWithObjects:
@"-c" ,
[NSString stringWithFormat:@"%@ '%@' '%@'", @"opendiff", source, target],
nil];
答案 0 :(得分:1)
shell的-c
选项将单字符串作为参数,而不是多个参数。使用NSString
以stringWithFormat
创建完整的shell命令行。在该字符串中,您应该像在终端中那样转义文件名,例如用单引号包围它们。在@"-c"
之后将此字符串作为参数传递。
HTH
答案 1 :(得分:0)
shell解释了许多特殊字符。使用双引号不足以使字符串安全。您可以尝试转义所有特殊字符,但这可能很挑剔。
最简单,最安全的方法是使用单引号。那些告诉shell将所有一直处理到下一个单引号并且没有解释。您唯一需要注意的是,如果您的字符串本身包含单引号。因此,以下两行将清理您的source
参数:
NSString* quoted_source = [source stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"];
quoted_source = [[@"'" stringByAppendingString:quoted_source] stringByAppendingString:@"'"];
第一行将任何嵌入的单引号转换为最终单引号(我们将在一瞬间开始),一个转义的单引号代替我们要替换的那个,然后是一个新的打开单引号。第二行用开头的单引号和结尾的结尾一行包装整个东西。