Если вы собираетесь использовать /bin/bash
в качестве пути запуска задачи, тогда вам нужно использовать список аргументов, который будет работать, если вы вызовете /bin/bash
в качестве команды, а не команду, как вы бы вводили как input в /bin/bash
командная строка. Это разные вещи.
То есть ваш код выполняет в оболочке примерно эквивалент следующей команды:
/bin/bash find some path here -type f -name "*.m" -exec sed -i '' "s/NSLog/\/\/NSLog/" {} +
Обратите внимание на /bin/bash
в начале этой команды. Также обратите внимание, что это не сработает. Наконец, я намеренно написал путь как «некоторый путь здесь» с пробелами, чтобы подчеркнуть, что ваша команда не предусматривает, что путь, в котором есть пробелы, будет рассматриваться как единственный аргумент для find
.
Если вы хотите запустить /bin/bash
и передать ему строку для интерпретации как команду, вам нужно использовать параметр -c
и передать строку команды в качестве единственного аргумента для этой опции -c
. Так:
/bin/bash -c 'find some path here -type f -name "*.m" -exec sed -i "" "s/NSLog/\/\/NSLog/" {} +'
Это решает одну из проблем. Это будет соответствовать:
task.arguments = @[ @"-c", arr ];
Это все еще не решает проблему с путем. Вы можете наивно попытаться решить эту проблему, изменив строку формата, заключив в кавычки спецификатор формата %@
, например:
NSString *arr = [NSString stringWithFormat:@"find \"%@\" -type f -name \"*.m\" -exec sed -i '' \"s/NSLog/\\/\\/NSLog/\" {} +",path];
Однако это не помогает, если в пути есть кавычки. Хуже того, это не помогает, если в пути есть специальные символы, такие как $ или `. Путь может быть интерпретирован оболочкой и выполнением подкоманд. Например, путь, в который входит $(rm -rf ~)
, будет катастрофическим.
Вы можете попробовать процитировать его в одинарные кавычки:
NSString *arr = [NSString stringWithFormat:@"find '%@' -type f -name \"*.m\" -exec sed -i '' \"s/NSLog/\\/\\/NSLog/\" {} +",path];
Но сам путь может включать одиночную кавычку, которая завершает цитирование, а затем специальные символы. Вредоносный путь просто меняется на '$(rm -rf ~)
.
Можно правильно указать путь в кавычки, но в целом глупо использовать оболочку, когда в этом нет необходимости.
Намного лучше напрямую вызвать исполняемый файл, который вы хотите запустить (/usr/bin/find
), и передать ему аргументы. Здесь нет оболочки, поэтому нет риска интерпретации каких-либо аргументов оболочкой.
So:
task.launchPath = @"/usr/bin/find";
task.arguments = @[ path, @"-type", @"f", @"-name", @"*.m", @"-exec", @"sed", @"-i", @"", @"s/NSLog/\\/\\/NSLog/\", @"{}", @"+" ];
Еще лучше выполнить перечисление каталогов - то, что вы здесь используете find
- в коде, поскольку это просто.
NSURL* url = [NSURL fileURLWithPath:path];
NSFileManager* fm = [[NSFileMananger alloc] init];
// Consider passing NSDirectoryEnumerationSkipsPackageDescendants in the options
NSDirectoryEnumerator* e = [fm enumeratorAtURL:url includingPropertiesForKeys:nil options:0 errorHandler:nil];
for (NSURL* item in e)
{
if ([item.pathExtension isEqualToString:@"m"])
{
// Use NSTask to run your /usr/bin/sed command on the item
}
}
Наконец, похоже, что команда, которую вы передаете sed
, не может работать. Может быть, ему нужен другой уровень экранирования (против компилятора C и самого sed
), но проще просто не рассматривать косую черту как специальный символ. Вы можете и должны использовать другой разделитель вокруг шаблона, если хотите использовать косую черту в замене. Например: s!NSLog!//NSLog!
.
person
Ken Thomases
schedule
27.02.2016
task.arguments
дает правильный ответ? - person matt   schedule 27.02.2016