Chciałbym móc użyć wyniku ostatnio wykonanego polecenia w kolejnym poleceniu. Na przykład,
$ find . -name foo.txt
./home/user/some/directory/foo.txt
Teraz powiedzmy, że chcę móc otworzyć plik w edytorze, usunąć go lub zrobić z nim coś innego, np.
mv <some-variable-that-contains-the-result> /some/new/location
Jak mogę to zrobić? Może używając jakiejś zmiennej bash?
Aktualizacja:
Aby wyjaśnić, nie chcę przypisywać rzeczy ręcznie. To, czego szukam, to coś w rodzaju wbudowanych zmiennych bash, np
ls /tmp
cd $_
$_
przechowuje ostatni argument poprzedniego polecenia. Chcę czegoś podobnego, ale z wyjściem ostatniego polecenia.
Ostateczna aktualizacja:
Odpowiedź Setha zadziałała całkiem nieźle. Kilka rzeczy, o których należy pamiętać:
- nie zapomnij o tym
touch /tmp/x
, próbując rozwiązania po raz pierwszy - wynik zostanie zapisany tylko wtedy, gdy kod zakończenia ostatniego polecenia powiódł się
linux
bash
command-line
armandino
źródło
źródło
Odpowiedzi:
To naprawdę hakerskie rozwiązanie, ale wydaje się, że czasami działa. Podczas testów zauważyłem, że czasami nie działało to zbyt dobrze, gdy otrzymywałem znak ^Cw wierszu poleceń, chociaż trochę go poprawiłem, aby zachowywał się trochę lepiej.
Ten hack to hack tylko w trybie interaktywnym i jestem pewien, że nie poleciłbym go nikomu. Polecenia w tle prawdopodobnie spowodują nawet mniej zdefiniowane zachowanie niż normalnie. Inne odpowiedzi to lepszy sposób na programowe uzyskiwanie wyników.
Biorąc to pod uwagę, oto „rozwiązanie”:
Ustaw tę zmienną środowiskową bash i wydaj polecenia zgodnie z potrzebami.
$LAST
zazwyczaj będzie miał wynik, którego szukasz:źródło
PROMPT_COMMAND='last="$(cat /tmp/last)";lasterr="$(cat /tmp/lasterr)"; exec >/dev/tty; exec > >(tee /tmp/last); exec 2>/dev/tty; exec 2> >(tee /tmp/lasterr)'
co zapewnia zarówno$last
i$lasterr
.No such file or directory
2> >(tee /tmp/lasterr 1>&2)
ponieważ standardowe wyjścietee
musi zostać przekierowane z powrotem do standardowego błędu.Nie znam żadnej zmiennej, która robi to automatycznie . Aby zrobić coś innego niż tylko skopiować i wkleić wynik, możesz ponownie uruchomić to, co właśnie zrobiłeś, np
Gdzie
!!
jest rozwinięcie historii oznaczające „poprzednie polecenie”.Jeśli spodziewasz się, że będzie istniała pojedyncza nazwa pliku ze spacjami lub innymi znakami, które mogą uniemożliwić poprawne analizowanie argumentów, zacytuj wynik (
vim "$(!!)"
). Pozostawienie go bez cudzysłowu umożliwi jednoczesne otwieranie wielu plików, o ile nie zawierają one spacji ani innych tokenów analizujących powłokę.źródło
vim `!!`
date "+%N"
a następnieecho $(!!)
Bash to trochę brzydki język. Tak, możesz przypisać wyjście do zmiennej
Ale lepiejfind
miej nadzieję, że najtrudniejszy wynik, który zwrócił tylko jeden wynik i że ten wynik nie zawiera żadnych "dziwnych" znaków, takich jak powrót karetki lub wysunięcie wiersza, ponieważ zostaną one po cichu zmodyfikowane po przypisaniu do zmiennej Bash.Ale lepiej uważaj, aby poprawnie cytować zmienną podczas jej używania!
Lepiej działać na plik bezpośrednio, na przykład z
find
„s-execdir
(zapoznać się z instrukcją).lub
źródło
echo "${MY_VAR}"
zobaczysz, że tak jest.Można to zrobić na więcej niż jeden sposób. Jednym ze sposobów jest użycie,
v=$(command)
które przypisze wyjście polecenia dov
. Na przykład:Możesz też używać odwrotnych cytatów.
Z przewodnika Bash dla początkujących ,
EDYCJA: Po edycji w pytaniu wydaje się, że nie jest to rzecz, której szuka PO. O ile wiem, nie ma specjalnej zmiennej, jak
$_
w przypadku ostatniego polecenia.źródło
To całkiem proste. Użyj cudzysłowów wstecznych:
A potem możesz użyć tego w dowolnym momencie w przyszłości
źródło
Disclamers:
Uruchamiając interaktywną powłokę w tmux, możesz łatwo uzyskać dostęp do danych aktualnie wyświetlanych na terminalu. Rzućmy okiem na kilka interesujących poleceń:
Tak, daje nam to teraz wiele możliwości :) Jeśli chodzi o mnie, ustawiłem prosty alias:
alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1"
i teraz za każdym razem, gdy potrzebuję uzyskać dostęp do ostatniej linii, po prostu używam,$(L)
aby ją uzyskać.Jest to niezależne od strumienia wyjściowego używanego przez program (czy to stdin, czy stderr), metody drukowania (ncurses itp.) I kodu wyjścia programu - wystarczy wyświetlić dane.
źródło
Myślę, że możesz być w stanie zhakować rozwiązanie, które wymaga ustawienia powłoki na skrypt zawierający:
Następnie, jeśli ustawisz
$PROMPT_COMMAND
wyjście separatora, możesz napisać funkcję pomocniczą (może nazywaną_
), która pobierze ostatnią porcję tego dziennika, więc możesz jej używać w następujący sposób:źródło
Możesz ustawić następujący alias w swoim profilu bash:
Następnie, wpisując „s” po dowolnym poleceniu, można zapisać wynik w zmiennej powłoki „it”.
Tak więc przykładowe użycie to:
źródło
grab
funkcję, która kopiuje n-ty wiersz z ostatniego polecenia do schowka gist.github.com/davidhq/f37ac87bc77f27c5027eWłaśnie wydestylowałem tę
bash
funkcję z sugestii tutaj:Następnie po prostu wykonaj:
Aktualizacja : anonimowy użytkownik zasugerowany do zastąpienia
echo
,printf '%s\n'
który ma tę zaletę, że nie przetwarza opcji, jak-e
w pobranym tekście. Tak więc, jeśli spodziewasz się lub doświadczasz takich osobliwości, rozważ tę sugestię. Inną opcją jest użyciecat <<<$grab
zamiast tego.źródło
cat <<<$grab
opcję?man bash
: „Tutaj Ciągi znaków: Wariant dokumentów tutaj, format:<<<word
Słowo jest interpretowane i dostarczane do polecenia na jego standardowym wejściu”. Tak więc wartość$grab
jest przekazywanacat
na stdin icat
po prostu przekazuje ją z powrotem na standardowe wyjście.Mówiąc „Chciałbym móc użyć wyniku ostatnio wykonanego polecenia w kolejnym poleceniu”, zakładam - masz na myśli wynik dowolnego polecenia, a nie tylko znajdź.
Jeśli tak jest - xargs jest tym, czego szukasz.
find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}
LUB jeśli chcesz najpierw zobaczyć wyniki:
find . -name foo.txt -print0
!! | xargs -0 -I{} mv {} /some/new/location/{}
To polecenie obsługuje wiele plików i działa jak urok, nawet jeśli ścieżka i / lub nazwa pliku zawiera spacje.
Zwróć uwagę na część polecenia mv {} / some / new / location / {} . To polecenie jest budowane i wykonywane dla każdej linii drukowanej przez wcześniejsze polecenie. Tutaj wiersz wydrukowany przez wcześniejsze polecenie jest zastępowany w miejsce {} .
Fragment ze strony podręcznika xargs:
Więcej szczegółów znajdziesz na stronie podręcznika:
man xargs
źródło
Przechwyć dane wyjściowe za pomocą grawitacji:
źródło
Zwykle robię to, co sugerowali inni tutaj ... bez przydziału:
Możesz stać się bardziej wyhodowany, jeśli chcesz:
źródło
Jeśli wszystko, czego chcesz, to ponowne uruchomienie ostatniego polecenia i uzyskanie wyniku, zadziała prosta zmienna bash:
Więc możesz uruchomić polecenie na wyjściu za pomocą:
Spowoduje to powstanie nowego procesu i ponowne uruchomienie polecenia, a następnie da wynik. Wygląda na to, że naprawdę chciałbyś, aby był to plik historii bash do wyjścia polecenia. Oznacza to, że będziesz musiał przechwycić dane wyjściowe, które bash wysyła do twojego terminala. Mógłbyś napisać coś do obejrzenia / dev lub / proc, ale to niechlujne. Możesz także po prostu utworzyć „specjalną potokę” między swoim terminem a bash z poleceniem tee w środku, które przekierowuje do pliku wyjściowego.
Ale oba są rodzajem hackerskich rozwiązań. Myślę, że najlepszą rzeczą byłby terminator, który jest bardziej nowoczesnym terminalem z rejestrowaniem danych wyjściowych. Po prostu sprawdź plik dziennika, aby sprawdzić wyniki ostatniego polecenia. Zmienna bash podobna do powyższej uczyniłaby to jeszcze prostszym.
źródło
Oto jeden sposób, aby to zrobić po wykonaniu polecenia i zdecydowaniu, że chcesz zapisać wynik w zmiennej:
Lub jeśli wiesz z wyprzedzeniem, że chcesz, aby wynik był w zmiennej, możesz użyć odwrotnych apostrofów:
źródło
Jako alternatywa dla istniejących odpowiedzi: użyj,
while
jeśli nazwy plików mogą zawierać spacje, takie jak:Jak napisałem, różnica jest istotna tylko wtedy, gdy w nazwach plików trzeba się spodziewać spacji.
NB: jedyne wbudowane rzeczy nie dotyczą wyjścia, ale statusu ostatniego polecenia.
źródło
możesz użyć !!: 1. Przykład:
źródło
Miałem podobną potrzebę, w której chciałem wykorzystać wyjście ostatniego polecenia do następnego. Podobnie jak | (rura). na przykład
na coś takiego -
Rozwiązanie: utworzono tę niestandardową rurę. Naprawdę proste, używając xargs -
W zasadzie nic, tworząc krótkie rozdanie dla xargs, działa jak urok i jest naprawdę przydatne. Po prostu dodaję alias w pliku .bash_profile.
źródło
Można to zrobić za pomocą magii deskryptorów plików i
lastpipe
opcji powłoki.Trzeba to zrobić za pomocą skryptu - opcja „lastpipe” nie będzie działać w trybie interaktywnym.
Oto skrypt, z którym testowałem:
To, co tu robię, to:
ustawienie opcji powłoki
shopt -s lastpipe
. Bez tego nie zadziała, ponieważ utracisz deskryptor pliku.upewniając się, że mój stderr również zostanie przechwycony
2>&1
przesyłanie danych wyjściowych do funkcji, aby można było odwołać się do deskryptora pliku stdin.
ustawienie zmiennej poprzez pobranie zawartości pliku
/proc/self/fd/0
deskryptora pliku, którym jest stdin.Używam tego do przechwytywania błędów w skrypcie, więc jeśli wystąpi problem z poleceniem, mogę przerwać przetwarzanie skryptu i od razu wyjść.
W ten sposób mogę dodać
2>&1 | exit_tests ; [[ "${PIPESTATUS[0]}" == "0" ]] || error_msg
każde polecenie, które chcę sprawdzić.Teraz możesz cieszyć się swoją produkcją!
źródło
Nie jest to rozwiązanie ściśle bash, ale możesz użyć potoku z sedem, aby uzyskać wynik ostatniego wiersza poprzednich poleceń.
Najpierw zobaczmy, co mam w folderze „a”
Wtedy twój przykład z ls i cd zamieniłby się w sed & piping w coś takiego:
Tak więc prawdziwa magia dzieje się z sedem, potokujesz wszystko, co kiedykolwiek wyjście z polecenia, do seda, a sed wypisuje ostatni wiersz, którego możesz użyć jako parametru z tylnymi tikami. Możesz też połączyć to z xargs. („człowiek xargs” w powłoce to twój przyjaciel)
źródło
Powłoka nie ma specjalnych symboli podobnych do perla, które przechowują wynik echa ostatniego polecenia.
Naucz się używać symbolu potoku w awk.
W powyższym przykładzie możesz zrobić:
źródło
to jeszcze jeden sposób, choć brudny.
źródło
Uważam, że pamiętam, aby potokować wyjście moich poleceń do określonego pliku, aby być nieco irytujące, moim rozwiązaniem jest funkcja w moim,
.bash_profile
która przechwytuje dane wyjściowe w pliku i zwraca wynik, kiedy go potrzebujesz.Zaletą tego jest to, że nie musisz ponownie uruchamiać całego polecenia (podczas używania
find
lub innych długotrwałych poleceń, które mogą być krytyczne)Wystarczająco proste, wklej to do swojego
.bash_profile
:Scenariusz
Stosowanie
W tym momencie staram się po prostu dodawać
| catch
na końcu wszystkie moje polecenia, ponieważ nie ma to żadnych kosztów i oszczędza mi konieczności ponownego uruchamiania poleceń, których zakończenie zajmuje dużo czasu.Ponadto, jeśli chcesz otworzyć plik wyjściowy w edytorze tekstu, możesz to zrobić:
źródło