Mam scenariusz, który wymaga zastąpienia poleceń bez użycia podpowłoki. Mam taki konstrukt:
pushd $(mktemp -d)
Teraz chcę wyjść i usunąć katalog tymczasowy za jednym razem:
rmdir $(popd)
Jednak to nie działa, ponieważ popd
nie zwraca wyskakującego katalogu (zwraca nowy, teraz aktualny katalog), a także dlatego, że jest wykonywany w podpowłoce.
Coś jak
dirs -l -1 ; popd &> /dev/null
zwróci wyskakujący katalog, ale nie można go użyć w następujący sposób:
rmdir $(dirs -l -1 ; popd &> /dev/null)
ponieważ popd
wpłynie tylko na podpowłokę. Potrzebna jest do tego zdolność:
rmdir { dirs -l -1 ; popd &> /dev/null; }
ale to nieprawidłowa składnia. Czy można osiągnąć ten efekt?
(uwaga: wiem, że mogę zapisać katalog tymczasowy w zmiennej; starałem się tego uniknąć i uczyłem się czegoś nowego!)
trap
moduł obsługi może wyczyścić katalog, jeśli proces zostanie zakłócony sygnałem.fish
, że jest to odpowiednik podstawiania poleceń()
, zmienia folder zewnętrznej powłoki. Jest to zwykle denerwujące, ale w takich przypadkach jest to przydatne, jestem pewien.Odpowiedzi:
Wybór tytułu pytania jest nieco mylący.
pushd
/popd
,csh
funkcja skopiowana przezbash
izsh
, jest sposobem zarządzania stosem zapamiętanych katalogów.wypycha bieżący katalog roboczy na stos, a następnie zmienia bieżący katalog roboczy (a następnie drukuje,
/some/dir
a następnie zawartość tego stosu (rozdzieloną spacjami).drukuje zawartość stosu (ponownie, oddzielając spację), a następnie zmienia się na górny element stosu i wyskakuje ze stosu.
(strzeż się również, że niektóre katalogi będą tam reprezentowane wraz z ich notacją
~/x
lub~user/x
zapisem).Więc jeśli stos obecnie ma
/a
i/b
, bieżący katalog to/here
i działasz:pushd
będzie drukować/tmp/whatever /here /a /b
ipopd
wyjście będzie/here /a /b
, nie/tmp/whatever
. Jest to niezależne od używania podstawiania poleceń, czy nie.popd
nie można użyć do uzyskania ścieżki do poprzedniego katalogu i ogólnie jego dane wyjściowe nie mogą zostać przetworzone (patrz jednak tablica$dirstack
lub$DIRSTACK
niektórych powłok w celu uzyskania dostępu do elementów tego stosu katalogów)Może chcesz:
Lub
Chociaż użyłbym:
W każdym razie
pushd "$(mktemp -d)"
nie działapushd
w podpowłoce. Jeśli tak, nie może zmienić katalogu roboczego. Tomktemp
działa w podpowłoce. Ponieważ jest to osobne polecenie, musi działać w osobnym procesie. Zapisuje dane wyjściowe na potoku, a proces powłoki odczytuje je na drugim końcu potoku.ksh93 może uniknąć oddzielnego procesu, gdy polecenie jest wbudowane, ale nawet tam jest to podpowłoka (inne środowisko robocze), które tym razem jest emulowane, zamiast polegać na oddzielnym środowisku zapewnianym zwykle przez rozwidlenie. Na przykład, w
ksh93
,a=0; echo "$(a=1; echo test)"; echo "$a"
żaden rozwidlenie nie jest zaangażowane, ale nadalecho "$a"
generuje0
.Tutaj, jeśli chcesz przechowywać dane wyjściowe
mktemp
w zmiennej, w tym samym czasie jak przekazać gopushd
, zzsh
, można zrobić:Z innymi pociskami podobnymi do Bourne'a:
Lub, aby użyć wyniku
$(mktemp -d)
kilka razy bez wyraźnego przechowywania go w zmiennej, możesz użyćzsh
funkcji anonimowych:źródło
pushd
ipopd
działam tak, jak to opisujesz i że są one niezależne od zastępowania poleceń - nie ma zamieszania! Jednak odpowiedziałeś własnym problemem ujawniając$OLDPWD
. Mogę zrobićpopd; rmdir $OLDPWD
. To jest odpowiedź na mój problem - wszystko inne tylko potwierdza to, co myślałem. Wydaje się, że podstawianie poleceń jest sposobem na jego rozwiązanie, ale nie dzieje się tak z powodu podpowłoki i nie można wykonać podstawiania poleceń bez podpowłoki, więc dziękuję za ujawnienie OLDPWD - właśnie tego potrzebuję!rmdir $(popd)
powodujepopd
uruchomienie w podpowłoce, co oznacza, że nie zmieni bieżącego katalogu, ale nawet jeśli nie uruchomił się w podpowłoce, wyjściempopd
nie będzie katalog tymczasowy, będzie to lista rozdzielona spacjami katalogów nie zawierających tej temp. reż. Mówię, że jesteś zdezorientowany.OLDPWD
. Muszę pamiętać, aby któregoś dnia czytaćman bash
od końca do końca!Możesz najpierw odłączyć katalog, zanim go opuścisz:
lub
ale zauważmy, że
pushd
ipopd
tak naprawdę są narzędziami do interaktywnych powłok, a nie skryptów (dlatego są tak rozmowni; prawdziwe polecenia skryptowe milczą, gdy im się powiedzie).źródło
W bash
dirs
podaj listę zapamiętanych katalogów metodą pushd / popd.Również
dirs -1
drukuje ostatni katalog zawarty w wykazie.Tak więc, aby usunąć katalog utworzony wcześniej przez wykonanie
pushd $(mktmp -d)
, użyj:A następnie
popd
już usunięty katalog z listy:Wszystko w jednym wierszu:
I dodanie opcji (-l), aby uniknąć
~/x
lub~user/x
notacji:Co jest niezwykle podobne do linii, o którą prosiłeś.
Tyle że nie użyłbym
&>
tego, ponieważ ukryłoby to jakiekolwiek raportowanie błędów przezpopd
.Uwaga: katalog pozostanie później,
rmdir
ponieważ jestpwd
w tym momencie. I będzie faktycznie rozłączony popopd
komendzie (żadne pozostałe łącza nie zostaną użyte).Istnieje opcja użycia dla powłok obsługujących zmienną „OLDPWD” (większość powłok typu bourne: ksh, bash, zsh have
$OLDPWD
). Warto zauważyć, że ksh domyślnie nie implementuje katalogów, pod, pushd (lksh, dash i inne również nie mają popd dostępne, więc nie można ich tutaj używać):Lub bardziej idiomatyczny (ta sama lista muszli jak powyżej):
źródło
rmdir
w bieżącym katalogu, gdzie byłbyś, robiąc to. Musisz topopd
zrobić przed zrobieniem,rmdir
ale musisz wiedzieć, co usunąć, ipopd
tego ci nie mówi. Ja, podobnie jak ty, myślałem, żedirs -l -1
to odpowiedź, ale od tamtej pory odkryłem, że ta odpowiedź jest rzeczywiście przydatna$OLDPWD
.popd && rmdir ~-
.rmdir "$PWD"
porządku. Ponadto bieżący katalog powinien być katalogiem utworzonym przezmktmp -d
(jeślipushd $(mktemp -d)
został wcześniej wykonany) i do któregopushd
przenosi pwd. Tak, popushd
i przed popd, utworzony katalog jest przechowywany w$(dirs -1)
, nie widzę żadnego problemu.