Jak mogę wykonać polecenie terminalu (jak grep
) z mojej aplikacji Objective-C Cocoa?
objective-c
cocoa
macos
lostInTransit
źródło
źródło
/usr/bin
miejscegrep
zamieszkania.Odpowiedzi:
Możesz użyć
NSTask
. Oto przykład, który działałby „/usr/bin/grep foo bar.txt
”.NSPipe
iNSFileHandle
służą do przekierowania standardowego wyjścia zadania.Bardziej szczegółowe informacje na temat interakcji z systemem operacyjnym z poziomu aplikacji Objective-C można znaleźć w tym dokumencie w Centrum programistycznym Apple: Interakcja z systemem operacyjnym .
Edycja: Dołączona poprawka dla problemu NSLog
Jeśli używasz NSTask do uruchamiania narzędzia wiersza poleceń poprzez bash, musisz dołączyć tę magiczną linię, aby NSLog działał:
Wyjaśnienie znajduje się tutaj: https://web.archive.org/web/20141121094204/https://cocoadev.com/HowToPipeCommandsWithNSTask
źródło
NSMutableData *data = [NSMutableData dataWithCapacity:512];
. Potemwhile ([task isRunning]) { [data appendData:[file readDataToEndOfFile]]; }
. I „wierzę”, że powinieneś mieć jeszcze jeden[data appendData:[file readDataToEndOfFile]];
po wyjściu z pętli while.task.standardError = pipe;
Artykuł Kent dał mi nowy pomysł. ta metoda runCommand nie potrzebuje pliku skryptu, po prostu uruchamia polecenie za pomocą wiersza:
Możesz użyć tej metody w następujący sposób:
źródło
w duchu udostępniania ... jest to metoda, której często używam do uruchamiania skryptów powłoki. możesz dodać skrypt do pakietu produktu (w fazie kopiowania kompilacji), a następnie odczytać skrypt i uruchomić go w czasie wykonywania. Uwaga: ten kod szuka skryptu w ścieżce podrzędnej privateFrameworks. ostrzeżenie: może to stanowić zagrożenie bezpieczeństwa dla wdrożonych produktów, ale dla naszego wewnętrznego rozwoju jest to łatwy sposób dostosowywania prostych rzeczy (takich jak host do rsync do ...) bez ponownej kompilacji aplikacji, ale po prostu edytując skrypt powłoki w pakiecie.
Edycja: Dołączona poprawka dla problemu NSLog
Jeśli używasz NSTask do uruchamiania narzędzia wiersza poleceń poprzez bash, musisz dołączyć tę magiczną linię, aby NSLog działał:
W kontekście:
Wyjaśnienie znajduje się tutaj: http://www.cocoadev.com/index.pl?NSTask
źródło
Oto jak to zrobić w Swift
Jest to oparte na powyższej odpowiedzi Inkit na Objective-C. Pisał go jako kategorii sprawie
NSString
- do szybkiego, staje się rozszerzenie zString
.rozszerzenie String.runAsCommand () -> String
Stosowanie:
Lub tylko:
Przykład:
Zwróć uwagę, że
Process
wynik odczytany zPipe
jestNSString
obiektem. Może to być ciąg błędu i może to być również ciąg pusty, ale zawsze powinien to być ciągNSString
.Tak więc, dopóki nie jest zero, wynik może być rzucony jako Szybki
String
i powrócił.Jeśli z jakiegoś powodu
NSString
w ogóle nie można zainicjować z danych pliku, funkcja zwraca komunikat o błędzie. Funkcja mogła zostać napisana w celu zwrócenia opcjonalnegoString?
, ale byłoby to niewygodne w użyciu i nie służyłoby pożytecznemu celowi, ponieważ tak mało prawdopodobne jest, aby tak się stało.źródło
Cel C (patrz Swift poniżej)
Wyczyściłem kod w górnej odpowiedzi, aby był bardziej czytelny, mniej zbędny, dodał zalety metody jednowierszowej i przekształcił się w kategorię NSString
Realizacja:
Stosowanie:
A jeśli masz problemy z kodowaniem wyjściowym:
Mam nadzieję, że będzie to dla ciebie równie przydatne, jak dla mnie przyszłości. (Witam Cię!)
Szybki 4
Oto przykład użycie Swift making of
Pipe
,Process
iString
Stosowanie:
źródło
fork , exec i wait powinny działać, jeśli tak naprawdę nie szukasz sposobu specyficznego dla Objective-C.
fork
tworzy kopię aktualnie działającego programu,exec
zastępuje aktualnie działający program nowym iwait
czeka na zakończenie podprocesu. Na przykład (bez sprawdzania błędów):Istnieje również system , który uruchamia polecenie tak, jakbyś wpisał je z wiersza poleceń powłoki. To prostsze, ale masz mniejszą kontrolę nad sytuacją.
Zakładam, że pracujesz nad aplikacją na komputery Mac, więc linki prowadzą do dokumentacji Apple dla tych funkcji, ale są one wszystkie
POSIX
, więc powinieneś używać ich w dowolnym systemie zgodnym z POSIX.źródło
Istnieje również stary, dobry system POSIX („echo -en '\ 007'”);
źródło
Incorrect NSStringEncoding value 0x0000 detected. Assuming NSStringEncodingASCII. Will stop this compatibility mapping behavior in the near future.
Napisałem tę funkcję „C”, ponieważ
NSTask
jest wstrętna ..och, a dla zachowania kompletności / jednoznaczności…
Wiele lat później
C
dla mnie nadal jest oszałamiający bałagan… i z niewielką wiarą w moją zdolność do skorygowania moich rażących niedociągnięć powyżej - jedyną gałązką oliwną, którą oferuję, jest zmieniona wersja odpowiedzi @ inket, która jest najzupełniej kośćca , dla moich kolegów purystów / nienawistnych hejterów ...źródło
Custos Mortem powiedział:
W przypadku problemów związanych z blokowaniem / nieblokowaniem połączeń, o których
NSTask
mowa poniżej:Kod źródłowy asynctask.m jest dostępny na GitHub .
źródło
Oprócz kilku doskonałych odpowiedzi powyżej, używam następującego kodu do przetwarzania danych wyjściowych polecenia w tle i unikania mechanizmu blokowania
[file readDataToEndOfFile]
.źródło
Lub ponieważ celem C jest po prostu C z warstwą OO na górze, możesz użyć elementów posix:
Są one zawarte w pliku nagłówkowym unistd.h.
źródło
Jeśli polecenie Terminal wymaga uprawnień administratora (alias
sudo
), użyjAuthorizationExecuteWithPrivileges
zamiast tego. Poniżej utworzy się plik o nazwie „com.stackoverflow.test” to katalog główny „/ System / Library / Caches”.źródło