Czy można zastąpić wbudowane polecenie „cd” wiersza poleceń?

22

Prawie za każdym razem, gdy „cd” do innego katalogu na moim komputerze (w tym przypadku z systemem Mac OS X 10.6.7) za pomocą wiersza polecenia (którym jest bash), natychmiast wpisuję „ls”, aby uzyskać listę zawartości w tym katalogu. Próbuję wymyślić sposób na zastąpienie „cd”, aby zmienił się na żądany katalog, a następnie dał mi listę w jednym ujęciu.

Udało mi się uzyskać podstawową funkcjonalność, której szukam, dodając następujący wiersz do mojego ~ / .bash_profile

function cl() { cd "$@"; ls -l; }

Działa to zgodnie z oczekiwaniami. Przejście do żądanego katalogu, a następnie wyświetlenie mi zawartości. W miejscu, w którym mam problem, próbuję zastąpić samą „cd” zamiast tworzyć nowe polecenie „cl”.

Następujące rzeczy nie działają

##### Attempt 1 #####
# Hangs the command line

function cd() { cd "$@"; ls -l; }


##### Attempt 2 #####
# Hangs the command line

function cd() { 'cd' "$@"; ls -l; }


##### Attempt 3 #####
# Does not change directory. 
# Does list contents, but of the directory where you started.

function cd() { /usr/bin/cd "$@"; ls -l; }


#### Other attempts that fail in various ways #####
alias cd=cd "$@"; ls -la;
alias cd="cd '$@'; ls -la;"
alias cd='cd "$@"'; ls -la;
alias cd=/usr/bin/cd "$@"; ls -la;

Próbowałem także kilku innych iteracji, których nie ma na liście, a także utworzyłem alias wskazujący działającą funkcję „cl”. Żaden z nich nie działał.

To, co przeczytałem w dokumentacji, mówi o tym, że „cd” nie może być uruchamiane jako polecenie zewnętrzne (co rozumiem jako sposób, w jaki funkcja musiałaby go użyć).

Tak więc mogę obecnie użyć polecenia „cl” i uzyskać to, czego chcę, ale pytanie brzmi / pozostaje:

Czy istnieje sposób na przesłonięcie zachowania „cd”, aby zmienić go na żądany katalog, a następnie zrobić coś innego?

Alan W. Smith
źródło

Odpowiedzi:

30

Następujące powinny działać:

function cd() { builtin cd "$@" && ls -l; }

Ponieważ funkcja znajduje się w jednej linii, upewnij się, że jest zakończona ;jak wyżej, aby działać poprawnie.

Gafel
źródło
Nie działa w przypadku wywołania bez parametrów.
Daniel Beck
3
@DanielBeck - przynajmniej w moim Mac OSX (10.6.7) działa to dobrze z wywołaniem bez parametrów. Zachowuje się tak, że przechodzi do katalogu domowego, a następnie robi listę tego katalogu. Skutecznie powiela funkcjonalność zwykłego „cd” z nową funkcją dodaną na końcu.
Alan W. Smith,
2
@Alan Prawda, przetestowałem to, pisząc ten kod ad-hoc w powłoce. Wygląda na to, że zachowanie cd ""(do tego, co ta odpowiedź powinna ocenić, różni się od cd "$@"pustego $@. Przepraszam za zamieszanie.
Daniel Beck
@DanielBeck - bez obaw.
Alan W. Smith,
2
Uwaga: Zmieniam to na zaakceptowaną odpowiedź, ponieważ jest to dokładna odpowiedź na pytanie. Ten autorstwa @RichHomolka doskonale nadaje się do adresowania zleceniodawcy, ale ten jest dokładnie tym, co można umieścić w pliku ~ / .bash_profile.
Alan W. Smith,
10

Myślę, że wpadasz w pętlę. Twoja cdfunkcja dzwoni cd, co jest ... funkcją.

Musisz wiedzieć, builtinktóre słowo kluczowe powoduje, że wyszukiwanie poleceń korzysta z wbudowanych poleceń Bash, takich jak cd, a nie z funkcji

function cd
{
    builtin cd "$1"
    : do something else
}

Również wywoływanie /usr/bin/cdnigdy nie zadziała, nawet jeśli takie polecenie istnieje.

Co by się stało:

  • Moja skorupa Bash jest w reż /bash/dir.
  • Wykonuję polecenie /usr/bin/cd /dir/for/cd.
  • /usr/bin/cdidzie do reż /dir/for/cd.
  • /usr/bin/cd wychodzi.
  • Bash jest nadal włączony /bash/dir, ponieważ proces potomny /usr/bin/cdnie może wpływać na element nadrzędny.

Aliasy to także proste podstawienia tekstu. Nigdy nie mogą mieć parametrów.

Rich Homolka
źródło
Proponuję builtin cd $@ && ls; ponieważ cdwezwanie powinno się powieść, aby wszystko inne miało sens. Pamiętaj również o szczególnych przypadkach, takich jak cd(bez argumentów).
Daniel Beck
Uwaga dodatkowa: Próbowałem zaznaczyć to jako zaakceptowaną odpowiedź, ale mówi mi to, że muszę poczekać kolejne 6 minut, zanim będę mógł to zrobić. Nie wiedziałem, że zanim to zrobisz, było wbudowane opóźnienie.
Alan W. Smith,
@Alan Kolejne, lepsze rozwiązanie może pojawić się w bardzo rozsądnych ramach czasowych (tj. Tych kilka minut, na które musisz czekać). Wydaje mi się, że dlatego opóźnienie jest obowiązkowe: powinieneś preferować jakość zamiast prędkości. Nie powinno to stanowić zbyt dużej niedogodności.
Daniel Beck
I mamy zwycięzcę. To działa jak mistrz. Na @DanielBeck zmieniłem się na && i skondensowałem go do jednej linii za pomocą: function cd {wbudowana płyta cd $ $ && ls -l; }
Alan W. Smith,
@DanielBeck - Tak, nie martwiłem się tym. Po prostu nigdy tego nie zauważyłem. Widzę w tym logikę, po prostu mnie trochę zaskoczyła.
Alan W. Smith,
6

Sugeruję, aby nie zastępować płyty cd, ponieważ istnieją inne skrypty przechwytujące funkcję „cd”, na przykład rvm. Lepiej byłoby wybrać inną nazwę, na przykład „d”, i nie określać typu „wbudowanego” w swojej funkcji; w przeciwnym razie porywacz nie działałby. Korzystam z poniższego kodu:

function d() { cd "$@" && ls;} 
Wen
źródło
Myślałem, że to nie zadziała, zgodnie z pytaniem PO.
user305964,