Como posso executar um comando de terminal (como grep
) do meu aplicativo Objective-C Cocoa?
objective-c
cocoa
macos
lostInTransit
fonte
fonte
/usr/bin
ondegrep
mora.Respostas:
Você pode usar
NSTask
. Aqui está um exemplo que seria executado '/usr/bin/grep foo bar.txt
'.NSPipe
eNSFileHandle
são usados para redirecionar a saída padrão da tarefa.Para obter informações mais detalhadas sobre como interagir com o sistema operacional no aplicativo Objective-C, consulte este documento no Centro de Desenvolvimento da Apple: Interagindo com o sistema operacional .
Editar: Correção incluída para o problema NSLog
Se você estiver usando o NSTask para executar um utilitário de linha de comando via bash, precisará incluir esta linha mágica para manter o NSLog funcionando:
Uma explicação está aqui: https://web.archive.org/web/20141121094204/https://cocoadev.com/HowToPipeCommandsWithNSTask
fonte
NSMutableData *data = [NSMutableData dataWithCapacity:512];
. Entãowhile ([task isRunning]) { [data appendData:[file readDataToEndOfFile]]; }
,. E eu "acredito" que você deve ter mais um[data appendData:[file readDataToEndOfFile]];
após o ciclo while terminar.task.standardError = pipe;
O artigo de Kent me deu uma nova idéia. esse método runCommand não precisa de um arquivo de script, apenas executa um comando por uma linha:
Você pode usar este método como este:
fonte
no espírito de compartilhar ... esse é um método que eu uso frequentemente para executar scripts de shell. você pode adicionar um script ao seu pacote de produtos (na fase de cópia da construção) e, em seguida, fazer com que o script seja lido e executado em tempo de execução. nota: esse código procura o script no subcaminho privateFrameworks. aviso: isso pode ser um risco à segurança dos produtos implantados, mas, para o nosso desenvolvimento interno, é uma maneira fácil de personalizar coisas simples (como qual host do rsync ...) sem recompilar o aplicativo, mas apenas editar o script de shell no pacote.
Editar: Correção incluída para o problema NSLog
Se você estiver usando o NSTask para executar um utilitário de linha de comando via bash, precisará incluir esta linha mágica para manter o NSLog funcionando:
No contexto:
Uma explicação está aqui: http://www.cocoadev.com/index.pl?NSTask
fonte
Veja como fazer isso no Swift
Isto é baseado na resposta Objective-C do inkit acima. Ele escreveu como uma categoria em
NSString
- Para Swift, isso se torna uma extensão deString
.extensão String.runAsCommand () -> String
Uso:
ou apenas:
Exemplo:
Observe o
Process
resultado como lido a partir dePipe
umNSString
objeto. Pode ser uma sequência de erros e também pode ser uma sequência vazia, mas sempre deve ser umaNSString
.Portanto, desde que não seja nulo, o resultado pode ser convertido em Swift
String
e retornado.Se, por algum motivo, não for
NSString
possível inicializar a partir dos dados do arquivo, a função retornará uma mensagem de erro. A função poderia ter sido escrita para retornar um opcionalString?
, mas seria difícil de usar e não serviria a um propósito útil, porque é muito improvável que isso ocorra.fonte
Objective-C (veja abaixo para Swift)
Limpou o código na resposta superior para torná-lo mais legível, menos redundante, adicionou os benefícios do método de uma linha e transformado em uma categoria NSString
Implementação:
Uso:
E se você estiver tendo problemas com a codificação de saída:
Espero que seja tão útil para você como será para o meu futuro. (Olá, você!)
Swift 4
Aqui está um exemplo Swift fazendo uso de
Pipe
,Process
eString
Uso:
fonte
fork , exec e wait devem funcionar, se você realmente não está procurando uma maneira específica de Objective-C.
fork
cria uma cópia do programa atualmente em execução,exec
substitui o programa atualmente em execução por um novo ewait
aguarda a saída do subprocesso. Por exemplo (sem nenhuma verificação de erro):Há também o sistema , que executa o comando como se você o digitasse na linha de comando do shell. É mais simples, mas você tem menos controle sobre a situação.
Suponho que você esteja trabalhando em um aplicativo Mac, então os links são para a documentação da Apple para essas funções, mas são todas
POSIX
, portanto, você deve usá-los em qualquer sistema compatível com POSIX.fonte
Também existe um bom sistema POSIX antigo ("echo -en '\ 007'");
fonte
Incorrect NSStringEncoding value 0x0000 detected. Assuming NSStringEncodingASCII. Will stop this compatibility mapping behavior in the near future.
Eu escrevi essa função "C", porque
NSTask
é desagradável ..ah, e por uma questão de ser completa / inequívoca…
Anos mais tarde,
C
ainda é uma confusão desconcertante, para mim .. e com pouca fé na minha capacidade de corrigir meus defeitos brutas acima - a oferta só ramo de oliveira que é uma versão rezhuzhed de resposta de @ inket que é mais desencapado dos ossos , para o meu companheiro puristas / odiadores da verbosidade ...fonte
Custos Mortem disse:
Para problemas de chamada de bloqueio / não bloqueio relacionados à
NSTask
leitura abaixo:O código fonte do asynctask.m está disponível no GitHub .
fonte
Além das várias excelentes respostas acima, eu uso o código a seguir para processar a saída do comando em segundo plano e evitar o mecanismo de bloqueio de
[file readDataToEndOfFile]
.fonte
Ou como o Objective C é apenas C com uma camada OO na parte superior, você pode usar as contrapartes posix:
Eles estão incluídos no arquivo de cabeçalho unistd.h.
fonte
Se o comando Terminal exigir privilégio de administrador (aka
sudo
), use em seuAuthorizationExecuteWithPrivileges
lugar. A seguir, será criado um arquivo chamado "com.stackoverflow.test", o diretório raiz "/ System / Library / Caches".fonte