bash - jak potokować wynik z polecenia do cd

87

Jak mogę przesłać wynik z whichpolecenia do cd?

Oto, co próbuję zrobić:

which oracle | cd
cd < which oracle

Ale żaden z nich nie działa.

Czy jest na to sposób (zamiast oczywiście kopiować / wklejać)?

Edycja: po namyśle to polecenie nie powiedzie się, ponieważ plik docelowy NIE jest folderem / katalogiem .

Zastanawiam się więc i opracowuję teraz lepszy sposób na pozbycie się końcowej części „/ oracle” (sed lub awk, a nawet Perl) :)

Edycja: OK, to, co mam na końcu:

cd `which oracle | sed 's/\/oracle//g'`
Michael Mao
źródło
2
co daje ci polecenie, a nie katalog
Anycorn
próbujesz znaleźć katalog, w którym jest zainstalowany program? dirname, basename ?
Anycorn
@aaa: masz rację, myślę dirname jest lepszy, ponieważ wskazuje na „prawdziwym dir” nie dowiązania symbolicznego do pliku wykonywalnego oracle ... dlatego moja sed apporach zawiedzie :)
Michael Mao

Odpowiedzi:

129

Używasz potoku w przypadkach, gdy polecenie oczekuje parametrów ze standardowego wejścia. ( Więcej na ten temat ).

Z cdrozkazem tak nie jest. Katalog jest argumentem polecenia. W takim przypadku możesz użyć podstawiania poleceń. Użyj odwrotnych znaków lub, $(...)aby ocenić polecenie, zapisz je w zmiennej.

path=`which oracle`
echo $path # just for debug
cd $path

chociaż można to zrobić w dużo prostszy sposób:

cd `which oracle` 

lub jeśli ścieżka zawiera znaki specjalne

cd "`which oracle`"

lub

cd $(which oracle)

co jest odpowiednikiem notacji odwrotnego znaku, ale jest zalecane (znaki odwrotne można pomylić z apostrofami)

.. ale wygląda na to, że chcesz:

cd $(dirname $(which oracle))

(co pokazuje, że możesz łatwo używać zagnieżdżania)

$(...) (podobnie jak lewy apostrof) działają również w podwójnych cudzysłowach, co pomaga, gdy wynik może ostatecznie zawierać spacje.

cd "$(dirname "$(which oracle)")"

(Zauważ, że oba wyjścia wymagają zestawu podwójnych cudzysłowów).

mykhal
źródło
Fajne. Czy mógłbyś wyjaśnić trochę o tym, co się tutaj dzieje? To wygląda na zmienną dereferencję; czy jest jakaś domyślna zmienna tymczasowa, do której trafiają wyniki polecenia?
Nate W.,
Ahhh, zapomniałem o rywalizacji o grawerach :(
Michael Mao,
4
Musisz kolejną parę cytatów: cd "$(dirname "$(which oracle)")".
Philipp,
|Otwiera nowy proces, więc nawet jeśli cdczytać ze standardowego wejścia, cmd | cdnie będzie działać (czyli katalog bieżący w pierwotnym procesie pozostałaby taka sama).
Kyle Strand
24

Z dirname, aby uzyskać katalog:

cd $(which oracle | xargs dirname)

EDYCJA: uważaj na ścieżki zawierające spacje, zobacz komentarz @anishpatel poniżej


źródło
3
Użyj, cd "$(which oracle | xargs -0 dirname)"jeśli ścieżka może zawierać spacje. Flaga -0 dzieli wejście przez null, a nie białe znaki.
anishpatel
9
cd `which oracle`

Zwróć uwagę, że są to grawerunki (zwykle klawisz po lewej stronie 1 na klawiaturze amerykańskiej)

Cfreak
źródło
1
To nie działa, jeśli ścieżka zawiera spacje lub inne znaki „specjalne” i musisz usunąć nazwę pliku.
Philipp,
@Philipp, możesz tego użyć, jeśli twoja ścieżka ma specjalne znakicd "`which oracle`"
Ram Patra
4

OK, tutaj rozwiązanie wykorzystujące prawidłowe cytowanie:

cd "$(dirname "$(which oracle)")"

Unikaj cudzysłowów, są one mniej czytelne i zawsze cytują podstawienia procesu.

Philipp
źródło
2

Nie potrzebujesz potoku, możesz robić, co chcesz, używając rozszerzenia parametrów Bash!

Kolejna wskazówka: użyj "type -P" zamiast zewnętrznego polecenia "which", jeśli używasz Bash.

# test
touch /ls
chmod +x /ls
cmd='ls'
PATH=/:$PATH
if cmdpath="$(type -P "$cmd")" && cmdpath="${cmdpath%/*}" ; then
   cd "${cmdpath:-/}" || { echo "Could not cd to: ${cmdpath:-/}"; exit 1; }
else
   echo "No such program in PATH search directories: ${cmd}"
   exit 1
fi
bashfu
źródło
1

W odpowiedzi na edytowane pytanie możesz usunąć nazwę polecenia za pomocą dirname:

cd $(dirname `which oracle`)
David Z
źródło
To nie działa, jeśli ścieżka zawiera spacje lub inne znaki „specjalne”.
Philipp,
1
Łatwo naprawione przez podwójne cudzysłowy.
David Z