Zmień bieżący katalog ze skryptu Bash

190

Czy można zmienić bieżący katalog ze skryptu?

Chcę stworzyć narzędzie do nawigacji w katalogu w Bash. Utworzyłem skrypt testowy, który wygląda następująco:

#!/bin/bash
cd /home/artemb

Kiedy wykonuję skrypt z powłoki Bash, bieżący katalog się nie zmienia. Czy w ogóle można zmienić bieżący katalog powłoki ze skryptu?

artemb
źródło
2
Tylko sugestia ulepszenia: jeśli użyjesz pushd(prawdopodobnie przekierowano, aby >/dev/nullukryć jego dane wyjściowe) zamiast cd, możesz później powrócić do poprzedniego katalogu za pomocą popd.
mklement0

Odpowiedzi:

173

Musisz przekonwertować skrypt na funkcję powłoki:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

Powodem jest to, że każdy proces ma swój bieżący katalog, a po uruchomieniu programu z powłoki jest on uruchamiany w nowym procesie. Standardowe „cd”, „pushd” i „popd” są wbudowane w interpreter powłoki, aby miały wpływ na proces powłoki.

Ustawiając program jako funkcję powłoki, dodajesz własne polecenie w trakcie procesu, a następnie każda zmiana katalogu jest odzwierciedlana w procesie powłoki.

kręcony
źródło
2
jak byś to zrobił w tcsh?
joedborg
4
+1. Jedną z rzeczy, które zauważyłem, było w pliku, musimy zdefiniować funkcję przed jej wywołaniem. Może pomóc komuś tak niedoświadczonemu jak ja.
Bhushan
Jaka jest duża różnica między zdefiniowaniem funkcji a utworzeniem aliasu?
HelloGoodbye,
1
Po utworzeniu tego pliku myprog.sh i dodaniu go do pliku .bashrc, jak uruchomić skrypt? Czy powinienem wywoływać moją funkcję z innego pliku powłoki czy bezpośrednio z powłoki? Wygląda na to, że nie działa w żaden sposób ...
Andrea Silvestri
1
@AndreaSilvestri Albo wyloguj się i zaloguj ponownie, albo źródłowy plik .bashrc. Dodanie go do .bashrc nic nie robi, dopóki .bashrc nie zostanie uruchomiony.
Jon Strayer
214

Po uruchomieniu skryptu tworzony jest nowy proces, który dziedziczy tylko środowisko. Kiedy się kończy, kończy się. Twoje obecne środowisko pozostaje takie, jakie jest.

Zamiast tego możesz uruchomić skrypt w następujący sposób:

. myscript.sh

.Oceni skrypt w obecnej sytuacji, więc to może być zmieniona

Norbert Hartl
źródło
4
+1, ponieważ masz rację. Chociaż szczerze wątpię, że za każdym razem będzie potrzebował źródła skryptu zmieniającego katalog. Ponadto .shrozszerzenia są całkowicie eww. Nie używaj ich.
lhunath
1
Tak, zwykle lepiej nie używać tego w ten sposób. Przez większość czasu cieszysz się, że twoje obecne środowisko nie cierpi. Ale potem mam skrypty do wykonania niektórych zadań konfiguracyjnych, w tym zmiany we właściwym miejscu, a potem ja. oni też. Btw. .sh jest oczywiście kwestią stylu osobistego. Prawdopodobnie nie użyłbym tego podczas instalowania skryptów w całym systemie. Ale w moim ~ / bin używam ich, aby wiedzieć, co jest :)
Norbert Hartl
11
@lhunath Dlaczego rozszerzenia .sh są całkowicie eww?
Carl Pritchett,
1
@CarlPritchett Rozszerzenia nazw poleceń uważane za szkodliwe .
gniourf_gniourf
1
Dla mnie rozumowanie w tym artykule jest fałszywe. Wydaje się, że wynik był znany z góry, ale znalezienie przyczyn tego nie było takie łatwe. Więc uważam, że to kwestia osobistego stylu, nic więcej.
Norbert Hartl
55

W świetle nieczytelności i nadmiernej komplikacji odpowiedzi uważam, że to właśnie powinien zrobić wnioskodawca

  1. dodaj ten skrypt do PATH
  2. uruchom skrypt jako . scriptname

.(Kropka) będzie upewnić się, że skrypt nie jest prowadzony w powłoce dziecięcej.

Steven Penny
źródło
38

Łącząc powyższe, możesz utworzyć alias

alias your_cmd=". your_cmd"

jeśli nie chcesz pisać wiodącego „.” za każdym razem, gdy chcesz otrzymać skrypt w środowisku powłoki lub po prostu nie chcesz pamiętać, że należy to zrobić, aby skrypt działał poprawnie.

MergerMan
źródło
Czy to pozostanie trwałe po ponownym uruchomieniu?
SDsolar
1
@SDsolar Musisz dodać to do pliku ~ / .bashrc, aby było trwałe. Dla mnie działa jak urok.
Rafał G.
Można umieścić w ~ / .bash_aliases
Champ
@Champ ~/.bash_aliasesnie zawsze jest pozyskiwany podczas uruchamiania Bash.
Mateusz Piotrowski
31

Jeśli używasz bash, możesz wypróbować alias:

w pliku .bashrc dodaj ten wiersz:

alias p='cd /home/serdar/my_new_folder/path/'

kiedy wpiszesz „p” w wierszu poleceń, zmieni katalog.

akarca
źródło
1
+1 dla aliasu. funkcja powłoki jest interesująca, ale OP poprosił o prostą nawigację z cd. Domyślam się, że większość ludzi potrzebuje takiego skryptu do poruszania się po gałęziach kodu źródłowego i do tego alias jest wystarczający
Brad Dre
19

Jeśli uruchomisz skrypt bash, będzie on działał w bieżącym środowisku lub w środowisku swoich dzieci, nigdy na rodzicu.

Jeśli celem jest uruchomienie polecenia: goto.sh / home / test Następnie pracuj interaktywnie w / home / test jednym ze sposobów jest uruchomienie interaktywnej podpowłoki w skrypcie:

#!/bin/bash
cd $1
exec bash

W ten sposób będziesz w / home / test, dopóki nie wyjdziesz (wyjście lub Ctrl + C) tej powłoki.

philippe lhardy
źródło
Myślałem, że to rozwiąże problem z uruchomionym skryptem powłoki, ale zamiast tego uruchamia powłokę i zapomina, co chciałem.
vwvan
13

Dzięki pushd bieżący katalog jest wypychany na stos katalogów i jest zmieniany na podany katalog, popd umieszcza katalog na wierzchu stosu i przechodzi do niego.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
seb
źródło
2
To odpowiada na moje pytanie - aktywnie wdrażam to rozwiązanie za pomocą skryptu inicjującego S3 i działa ono doskonale. Dzięki @seb.
19h
5

Po prostu idź do

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

i dodaj ten kod obok ostatniego wiersza:

alias yourcommand="cd /the_path_you_wish"

Następnie zamknij edytor.

Następnie wpisz:

source ~/.bashrc or source ~/.bash_profile on MAC.

teraz możesz użyć: twoje polecenie w terminalu

ThangTD
źródło
3

Zasadniczo używamy cd..do powrotu z każdego katalogu. Pomyślałem, aby to ułatwić, podając liczbę katalogów, z którymi musisz wracać naraz. Możesz to zaimplementować za pomocą osobnego pliku skryptu za pomocą polecenia alias. Na przykład:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Po użyciu source code.shw bieżącej powłoce możesz użyć:

$back 2 

wrócić dwa kroki od bieżącego katalogu. Szczegółowo wyjaśnione tutaj . Wyjaśniono tam również, jak umieścić kod w ~ / .bashrc, aby każda nowa otwarta powłoka automatycznie otrzymywała nowe polecenie aliasu. Możesz dodać nowe polecenie, aby przejść do określonych katalogów, modyfikując kod, dodając więcej if conditionsi różne argumenty. Możesz także pobrać kod z git tutaj .

Arun Chettoor
źródło
Fajne rozwiązanie, więc nigdy nie
zepsujesz
0

To podejście jest dla mnie łatwiejsze.

Załóżmy, że na osobistym komputerze iMac, w którym jesteś administratorem, w domyślnym katalogu, gdy otwarte jest okno poleceń, / Users / jdoe, będzie to katalog, do którego można przejść: /Users/jdoe/Desktop/Mongo/db.3.2.1 /kosz.

Oto kroki, które można wykonać:

  1. vi mongobin, w którym wpisałem: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/binjako pierwszy wiersz.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!

Daniel C. Deng
źródło
0

Stworzyłem również narzędzie o nazwie koza , którego można używać w celu ułatwienia nawigacji.

Możesz zobaczyć kod źródłowy na GitHub .

Począwszy od v2.3.1 z przeglądu użycie wygląda następująco:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix
Mateusz Piotrowski
źródło
0

Lubię robić to samo dla różnych projektów bez uruchamiania nowej powłoki.

W Twoim przypadku:

cd /home/artemb

Zapisz skrypt jako:

echo cd /home/artemb

Następnie uruchom go za pomocą:

\`./the_script\`

Następnie przechodzisz do katalogu przy użyciu tej samej powłoki.

DrGamma
źródło
0

Dodaj poniżej linii cd w swoim shellscript to:

exec $SHELL
Alberto Corella
źródło
0

Zadeklaruj swoją ścieżkę:

PATH='/home/artemb'     
cd ${PATH}
m_sam
źródło
0

Po prostu napisz PWDi wyeksportuj go do skryptu, a zmiana będzie się utrzymywać.

export PWD=/your/desired/directory
Samha
źródło