Jag vill köra ett skript för att helt enkelt ändra den aktuella arbetskatalogen:
#!/bin/bash cd web/www/project
Men efter att jag kör det är den nuvarande pwd oförändrad! Hur kan jag göra det?
Svar
Det är ett förväntat beteende. Skriptet körs i en subshell och kan inte ändra den överordnade skalets arbetskatalog. Dess effekter går förlorade när den är klar.
För att ändra den aktuella skalkatalogen permanent bör du använda kommandot source
, även alias helt enkelt som .
, som kör ett skript i den aktuella skalmiljön istället för ett underskal.
Följande kommandon är identiska:
. script
eller
source script
Kommentarer
Svar
För små uppgifter som detta, istället för att skapa skript, skapa ett alias så här,
$ alias cdproj="cd /dir/web/www/proj"
Du bör lägga till detta i din .bashrc
-fil, om du vill att den ska ställas in för varje interaktivt skal.
Nu kan du köra den som $ cdproj
.
Kommentarer
- Du kan också låta manuset eka kommandona som ska köras och sedan använda
eval `./script`
ellereval $(./script)
för att utföra dessa kommandon. Detta är ett vanligt tillvägagångssätt för kommandon som behöver uppdatera det anropande skalet ’ s miljö. - Var bara mycket försiktig med vad du matar ut om du ska gå
eval
tillvägagångssätt.
Svar
Använd exec bash
i slutet
Ett bash-skript fungerar på sin nuvarande miljö eller på dess barn, men aldrig på dess föräldermiljö.
Denna fråga ställs dock ofta eftersom man vill lämnas vid bash fråga i en viss katalog efter körningen av ett bash-skript från en annan katalog.
Om detta är fallet, kör du bara en underordnad bash-instans i slutet av skriptet:
#!/usr/bin/env bash cd desired/directory exec bash
Detta skapar en ny subshell. Skriv Ctrl + D eller exit
för att återgå till det första skalet där skriptet ursprungligen startades.
Uppdatering
Åtminstone med nyare versioner av bash
är exec
på den sista raden inte längre nödvändig. Dessutom kan skriptet fungera med vilket föredraget skal som helst genom att använda miljövariabeln $SHELL
. Detta ger sedan:
#!/usr/bin/env bash cd desired/directory $SHELL
Kommentarer
- Bättre att bara källa skriptet, som i accepterat svar : att använda
exec
anses vanligtvis vara den sista utväg för en skurk … 🙂 - det här tricket ’ t arbeta i debian 9 stretch.
- Det här är fel sätt att göra detta!
- Eftersom ingen har beskrivit problemen med detta (jag tittar på dig, @Dennis): (1) Varje gång du kör detta skapar det en ny, ihållande bash-process. Gör det tio eller tjugo gånger i en session, så får du 11 till 21 bash-processer. Detta kan påverka prestandan och om du försöker avsluta sessionen rent genom att skriva
exit
(eller Ctrl + D) måste du göra det 11 till 21 gånger. (2) En annan nackdel med att använda ett körbart skript är att om du anger några skalalternativ (t.ex.dotglob
ellerglobstar
) interaktiv skalsession kommer du att förlora dem eftersom du startar ett nytt skal. - Mycket trevlig lösning! Jag ’ har skrivit om mitt alias i bash_profile så nu är det ett skript som lagras i en separat fil. Jag använder skriptet för att gå till en nyskapad tillfällig mapp. Och nu är det ännu lättare att ha en tillfällig bash-session. SRP i aktion! Tack!
Svar
Även om det finns svar som gör den exakta åtgärd som du vill, en mer standardmetod för sådana syftet är att skapa symbolisk länk:
ln -s ~/web/www/project proj #use full path to dir!
Då kan du cd
till katalogen med namnet proj
:
cd proj
Denna metod är mer flexibel eftersom du kan komma åt filer med det korta namnet utan cd
:
ls proj/ #note the endslash! vim proj/file.x
Svar
Beror på vad du ”kommer att göra, en annan lösning kan vara att skapa en funktion istället för ett skript.
Exempel:
Skapa en funktion i en fil, låt oss säga /home/aidin/my-cd-script
:
function my-cd() { cd /to/my/path }
Inkludera det sedan i din bashrc
eller zshrc
fil:
# Somewhere in rc file source /home/aidin/my-cd-script
Nu kan du använda den som ett kommando:
$ my-cd
Svara
Om du byter mellan kataloger långt borta i filsystemet. Jag kommer att rekommendera autojump .
Svar
För mig var det mest bekväma och flexibla tillvägagångssättet en blandning av ett alias och ett skript:
skapa skript med godtycklig logik
Här skapar jag ett skript som ändras till en katalog och aktiverar lämplig pythonmiljö. Skriptplatsen är exempel på /path/to/workon_myproj.sh
.
#!/usr/bin/env bash cd $HOME/workspace/myproj source .venv/bin/activate
skapa alias som källskript
alias workon_myproj="source /path/to/workon_myproj.sh"
Lägg till aliasdefinitionen i din lämpliga shell-startfil t.ex. .profile
, .bashrc
eller .zshrc
.
utfall
Du kan nu bara köra workon_myproj
i ett skal som kommer att källa till innehållet i ditt skript i önskad katalog.
töjbarhet
Du kan eventuellt förbättra ditt skript för att ta ett argument så att det fungerar med flera projekt i en viss arbetskatalog eller kombinera det med en git pull
för att få de senaste ändringarna omedelbart och så på … allt pannplattans grejer du gör när du fortsätter att arbeta med ett visst projekt.
Svar
Varför inte använda ” exec ”det sömmar att göra exakt vad jag önskar.
#!/bin/bash cd someplace exec bash ~/someplace
Kommentarer
- Se upp för saker som verkar vara vad du vill ha. (En jätte trähäst! Precis vad jag ville!) Varje gång du kör detta skapar det en ny, ihållande bash-process. Gör det tio eller tjugo gånger under en session, så har du 11 till 21 bash-processer staplade. Detta kan påverka prestandan och om du försöker avsluta sessionen rent genom att skriva
exit
(eller Ctrl + D) måste du göra det 11 till 21 gånger. - Jag kunde definitivt se var det skulle vara ett problem. För mig ändå ’ jag använder det en gång, gör det arbete jag behöver och sedan avslutar. Om det är ’ är jag kan leva med det. Å andra sidan om det finns en bättre lösning är jag ’ villig att titta på den.
- Aidins svar på den här frågan , med en skalfunktion, och Sachin Divekars svar , med hjälp av ett alias, är (IMO) bättre lösningar än att använda ett skript . P.S. En annan nackdel med att använda ett skript är att om du anger några skalalternativ (t.ex.
dotglob
ellerglobstar
) kommer du att förlora dem, för att du startar ett nytt skal. … (Fortsätt) - (Fortsätt) … P.P.S. Jag märkte bara att du i grund och botten upprepar Serge Stroobandts svar och säger Varför inte göra det här? Vid Stack Exchange vi förväntar oss att svar ger nya idéer och / eller information, och inte bara diskuterar andra svar.
Svar
Detta kombinerar svaret av Serge med ett orelaterat svar av David . Det ändrar katalogen och istället för att tvinga ett bash-skal startar det användarens standardskal . Det kräver dock både getent
och /etc/passwd
för att upptäcka standardskalet.
#!/usr/bin/env bash cd desired/directory USER_SHELL=$(getent passwd <USER> | cut -d : -f 7) $USER_SHELL
Naturligtvis har detta fortfarande samma brist att skapa ett kapslat skal.
Svar
Du kan göra det med en funktion eller med hjälp av & & Exemplen nedan installerar Zabbix och skapar en fil med en rad inuti.
Ex:
#!/bin/bash # Create Function: installZabbix(){ cd /usr/src/zabbix-4.2.4; ./configure --enable-agent; make install; cd /usr/src/; >file; echo "Hi, this is a file." >>file; } # Call the function: installZabbix
eller:
#!/bin/bash cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
return
för att fly från ett skript som härrör från detta sätt, inteexit
– de är som skalfunktioner ochexit
kommer att lämna skalet som skriptet har skaffat.source ./script
samma?.
ochsource
är lika i bash. 2. vi ’ behöver inte använda./
före filnamn om det ’ är i samma katalog. Det är ok att bara köra detta:. script