W php.ini
moim systemie jest około 10 plików rozmieszczonych w dowolnym miejscu i chciałem szybko je przeglądać. Próbowałem tego polecenia:
locate php.ini | xargs vi
Ale vi
ostrzega mnie, Input is not from a terminal
a potem konsola zaczyna się naprawdę dziwnie - po czym muszę nacisnąć, :q!
aby wyjść, vi
a następnie rozłączyć się z sesją ssh i połączyć się ponownie, aby konsola zachowała się normalnie.
Wydaje mi się, że rozumiem, co się tutaj dzieje - w zasadzie polecenie nie zakończyło się po vi
uruchomieniu, więc polecenie może się nie zakończyło i vi
nie wydaje się, że terminal jest w trybie normalnym.
Nie mam pojęcia, jak to naprawić. Przeszukałem Google, a także unix.stackexchange.com, ale przy odrobinie szczęścia.
reset
aby zresetować terminal, gdy zostanie zepsuty (nie musisz rozłączać się z sesją ssh).Odpowiedzi:
Uwaga: będzie to powodować problemy, jeśli ścieżki do plików mają spacje, ale jest funkcjonalnie równoważne z twoim poleceniem.
Następna wersja poprawnie obsługuje spacje, ale jest nieco bardziej skomplikowana (jednak nowe wiersze w nazwach plików nadal ją łamią)
Wyjaśnienie:
To, co się dzieje, polega na tym, że programy dziedziczą swoje deskryptory plików po procesie, który je zrodził.
xargs
ma swój STDIN podłączony do STDOUTlocate
, więcvi
nie ma pojęcia, w czym tak naprawdę jest oryginalny STDIN.źródło
xargs
do tego, czego nie można było zrobić bezpośrednio za pomocą powłoki (lubfind
). Mogę jednak myśleć o przypadkach, w których byłoby to najlepsze rozwiązanie. Tak długo, jak rozumiesz, coxargs
się dzieje, jak dzieli argumenty, jak uruchamia program itp. I używasz go poprawnie, powiedziałbym: idź po to :-P... | awk '{print $3}' | xargs | sed -e 's/ /+/g' | bc
(aby dodać wszystkie wartości z pola 3). lub z,sed -e 's/ /|/g'
aby skonstruować wyrażenie regularne. i tak, jak każde narzędzie, musisz wiedzieć, jak z niego korzystać oraz jakie są jego ograniczenia i zastrzeżenia.vi $(...)
Podejście ma również problemu z symboli wieloznacznych w muszli innych niżzsh
.xargs
podejściu obok problemu białych znaków nazwy plików z pojedynczymi cudzysłowami, podwójnymi cudzysłowami i odwrotnymi ukośnikami również stanowią problem.To pytanie zostało wcześniej zadane na forum Super User .
Cytując odpowiedź @ grawity na to pytanie:
Jest to wspomniane na stronach podręcznika dla xarg. Z OSX / BSD:
Dlatego w systemie OSX można użyć następującego polecenia:
Chociaż w wersji GNU nie ma bezpośredniego przełącznika, to polecenie będzie działać. (Pamiętaj, aby dołączyć
dummy
ciąg, w przeciwnym razie spowoduje upuszczenie pierwszego pliku).Powyższe rozwiązania są dzięki uprzejmości Jaime McGuigan na SuperUser . Dodanie ich tutaj dla przyszłych użytkowników przeszukujących witrynę pod kątem tego błędu.
źródło
xargs sh -c 'emacs "$@" < /dev/tty' emacs
ponieważ, jak twierdzą, jest bardziej elastyczną i przenośną alternatywą (chociaż to trochę zabawne, że GNU preferuje przenośność od funkcji :).Dzięki GNU
findutils
i powłoce z obsługą zastępowania procesów (ksh, zsh, bash) możesz:Chodzi o to, aby przekazać listę plików
-a filename
raczej niż przez standardowe wyjście. Użycie-0
powoduje, że działa niezależnie od znaków lub znaków innych niż nazwy plików.Dzięki
zsh
możesz wykonać:(gdzie
0
jest flaga ekspansji parametru do podziału na wartości NUL).Należy jednak pamiętać, że w przeciwieństwie do
xargs -r
tego nadal działavi
bez argumentów, jeśli nie znaleziono pliku.źródło
Edytować wiele php.ini w tym samym edytorze?
Próbować:
vim -o $(locate php.ini)
źródło
Ten błąd występuje, gdy vim jest wywoływany i jest podłączony do wyjścia poprzedniego potoku, zamiast terminala i otrzymuje inne nieoczekiwane dane wejściowe (takie jak NUL). To samo dzieje się po uruchomieniu:,
vim < /dev/null
więcreset
polecenie w tym przypadku pomaga. Wyjaśnia to dobrze grawitacja w superużytkowniku .W systemach Unix / OSX możesz używać
xargs
z-o
parametrem, takim jak:W systemie Linux wypróbuj następujące obejście:
Alternatywnie użyj GNU
parallel
zamiastxargs
wymusić alokację tty, na przykład:Uwaga:
parallel
w systemach Unix / OSX nie będzie działać, ponieważ ma inne parametry i nie obsługuje tty.Wiele innych popularnych poleceń zapewnia także alokację pseudo-tty (np
-t
wssh
), więc sprawdzić o pomoc.Alternatywnie użyj,
find
aby przekazać nazwy plików do edycji, więc nie musiszxargs
, po prostu użyj-exec
na przykład:źródło
@
IFS
Hack Patryka jest konieczny tylko dla głupich muszli takich jakbash
izsh
.fish
domyślnie dzieli ciąg na nowe linie.I Boże, pomóż nam wszystkim, jeśli jeden z nas rzeczywiście ma plik z nową linią w nazwie. Po 17 latach używania Linuksa nie widziałem go ani razu. Chciałbym tylko wspierać nazwy plików z nowymi wierszami dla skryptów, które muszą działać bez względu na wszystko, ale takie skrypty prawdopodobnie nie działają interaktywnie.
źródło
zsh
domyślnie dzieli na SPC, TAB, NL i NUL. Rzeczą, której nie robi w porównaniu z tym,bash
jest przeprowadzanie globowania wyniku, więc znaki wieloznaczne w nazwach plików nie stanowią problemu. Wzsh
, zrobiłbyśIFS=$'\0'; vi $(locate -0 php.ini)
lub jak pokazałem w mojej odpowiedzivi ${(0)"$(locate -0 php.ini)"}
dla jawnego operatora podziału. Zwróć też uwagę na tcshvi "`locate php.ini`"
$ f='not there'<ret>$ ls $f<ret>
ale to nie: lsecho not there
. OK wygląda na to, że muszę to trochę zaktualizować.ls "$(echo test; echo other test)"
. Tylko ryby robią to, co należy.$IFS
lub za pośrednictwem jawnych operatorów (f
i0
flag rozszerzania parametrów). W przypadku dowolnych nazw plików dzielenie według słów lub dzielenie według wierszy jest równie niepoprawne , musisz podzielić na NUL lub przeanalizować kodowanie, czegofish
nie można zrobić. Wzsh
, toIFS=$'\0'; ls -ld -- $(printf '%s\0' "$file1" "$file2")
lubls -ld -- ${(0)"$(printf '%s\0' "$file1" "$file2")"}
Szybkim sposobem, aby to zrobić, zakładając, że można zagwarantować żadna ze ścieżek plików zawierać SPC, TAB, NL,
*
,?
,[
znaków (także\
i{...}
w niektórych muszli) jest użycie back-kleszczy (aka grawis) , aby wykonać polecenie przed uruchomione kolejne polecenie.Na przykład
Polecenie zawarte w tykach zwrotnych zostanie wykonane jako pierwsze. Dane wyjściowe zawartego polecenia są następnie wykonywane przez polecenie podane przed tyknięciami wstecznymi.
Na przykład w powyższym wierszu
find / -type f -name 'php.ini'
polecenie wykona się najpierw, wyśle dane wyjściowe, a następnievi
zostanie wykonane na podstawie wyniku split + glob zastosowanego do tego wyniku.źródło
$(find ...)
zamiast tego.vi
użyciu tej metody. Jest całkiem możliwe, że może się złamać w nowych wierszach lub spacjach, w zależności od tego, jakvi
odczytuje i wykonuje dane wyjściowe.