Как я могу выполнить терминальную команду (например grep
) из моего приложения Objective-C Cocoa?
objective-c
cocoa
macos
lostInTransit
источник
источник
/usr/bin
где ониgrep
живут.Ответы:
Вы можете использовать
NSTask
. Вот пример, который будет запускаться '/usr/bin/grep foo bar.txt
'.NSPipe
иNSFileHandle
используются для перенаправления стандартного вывода задачи.Более подробную информацию о взаимодействии с операционной системой из приложения Objective-C вы можете найти в этом документе в Центре разработки Apple: Взаимодействие с операционной системой. .
Изменить: Включено исправление для проблемы NSLog
Если вы используете NSTask для запуска утилиты командной строки через bash, то вам нужно включить эту магическую строку, чтобы NSLog работал:
Объяснение здесь: https://web.archive.org/web/20141121094204/https://cocoadev.com/HowToPipeCommandsWithNSTask
источник
NSMutableData *data = [NSMutableData dataWithCapacity:512];
. Тогдаwhile ([task isRunning]) { [data appendData:[file readDataToEndOfFile]]; }
. И я «верю», что у вас должен быть еще один[data appendData:[file readDataToEndOfFile]];
после выхода из цикла while.task.standardError = pipe;
Статья Кента дала мне новую идею. этот метод runCommand не нуждается в файле сценария, он просто запускает команду по строке:
Вы можете использовать этот метод следующим образом:
источник
в духе обмена ... это метод, который я часто использую для запуска сценариев оболочки. Вы можете добавить сценарий в комплект вашего продукта (на этапе копирования сборки), а затем выполнить чтение и запуск сценария во время выполнения. примечание: этот код ищет скрипт в подпути privateFrameworks. предупреждение: это может быть угрозой безопасности для развернутых продуктов, но для нашей собственной разработки это простой способ настроить простые вещи (например, какой хост rsync для ...), не перекомпилируя приложение, а просто отредактировав скрипт оболочки в комплекте.
Изменить: Включено исправление для проблемы NSLog
Если вы используете NSTask для запуска утилиты командной строки через bash, то вам нужно включить эту магическую строку, чтобы NSLog работал:
В контексте:
Объяснение здесь: http://www.cocoadev.com/index.pl?NSTask
источник
Вот как это сделать в Swift
Это основано на ответе Obit-C от Inkit выше. Он написал ее в качестве категории по
NSString
- Для Swift, она становится продолжением изString
.расширение String.runAsCommand () -> String
Использование:
или просто:
Пример:
Обратите внимание на
Process
результат , как считывается изPipe
являетсяNSString
объектом. Это может быть строка ошибки, а также пустая строка, но она всегда должна бытьNSString
.Так что, пока это не ноль, результат можно разыграть как Swift
String
и вернуть.Если по каким-либо причинам
NSString
инициализация вообще не может быть выполнена из данных файла, функция возвращает сообщение об ошибке. Эта функция могла бы быть написана так, чтобы она возвращала необязательный параметрString?
, но это было бы неудобно для использования и не могло бы служить полезной цели, поскольку это вряд ли произойдет.источник
Objective-C (см. Ниже для Swift)
Очистили код в верхнем ответе, чтобы сделать его более читабельным, менее избыточным, добавили преимущества однострочного метода и превратили в категорию NSString
Реализация:
Использование:
И если у вас есть проблемы с кодировкой вывода:
Надеюсь, это так же полезно для вас, как и для меня в будущем. (Привет тебе!)
Swift 4
Вот Свифт использование пример изготовление
Pipe
,Process
иString
Использование:
источник
fork , exec и wait должны работать, если вы на самом деле не ищете специфический для Objective-C способ.
fork
создает копию запущенной в данный момент программы,exec
заменяет текущую запущенную программу новой иwait
ожидает завершения подпроцесса. Например (без проверки ошибок):Также есть система , которая запускает команду так, как будто вы набрали ее из командной строки оболочки. Это проще, но у вас меньше контроля над ситуацией.
Я предполагаю, что вы работаете над приложением Mac, поэтому ссылки приведены на документацию Apple по этим функциям, но они все
POSIX
, так что вы должны использовать их в любой POSIX-совместимой системе.источник
Существует также старая добросовестная система POSIX ("echo -en '\ 007'");
источник
Incorrect NSStringEncoding value 0x0000 detected. Assuming NSStringEncodingASCII. Will stop this compatibility mapping behavior in the near future.
Я написал эту функцию "C", потому что
NSTask
это неприятно ..о, и ради того, чтобы быть полным / однозначным ...
Годы спустя,
C
для меня это все еще изумительный беспорядок ... и с малой верой в мою способность исправить мои грубые недостатки выше - единственная оливковая ветвь, которую я предлагаю, это rezhuzhed версия ответа @ inket, которая является чуть-чуть костей для моего товарища пуристы / многословные ненавистники ...источник
Кастос Мортем сказал:
Для блокирующих / неблокирующих проблем звонка относительно
NSTask
прочитанных ниже:Исходный код asynctask.m доступен на GitHub .
источник
В дополнение к нескольким превосходным ответам, приведенным выше, я использую следующий код, чтобы обработать вывод команды в фоновом режиме и избежать механизма блокировки
[file readDataToEndOfFile]
.источник
Или, поскольку Objective C - это просто C с некоторым слоем OO сверху, вы можете использовать составные части posix:
Они включены в заголовочный файл unistd.h.
источник
Если для команды «Терминал» требуется привилегия администратора (aka
sudo
), используйтеAuthorizationExecuteWithPrivileges
вместо этого. Далее будет создан файл с именем «com.stackoverflow.test», являющийся корневым каталогом «/ System / Library / Caches».источник