Ändern Sie das aktuelle Verzeichnis aus einem Bash-Skript

190

Ist es möglich, das aktuelle Verzeichnis über ein Skript zu ändern?

Ich möchte ein Dienstprogramm für die Verzeichnisnavigation in Bash erstellen. Ich habe ein Testskript erstellt, das wie folgt aussieht:

#!/bin/bash
cd /home/artemb

Wenn ich das Skript über die Bash-Shell ausführe, ändert sich das aktuelle Verzeichnis nicht. Ist es überhaupt möglich, das aktuelle Shell-Verzeichnis von einem Skript aus zu ändern?

artemb
quelle
2
Nur ein Verbesserungsvorschlag: Wenn Sie stattdessen pushd(möglicherweise umgeleitet, >/dev/nullum die Ausgabe zu unterdrücken) verwenden cd, können Sie später mit zum vorherigen Verzeichnis zurückkehren popd.
mklement0

Antworten:

173

Sie müssen Ihr Skript in eine Shell-Funktion konvertieren:

#!/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
}

Der Grund dafür ist, dass jeder Prozess sein eigenes aktuelles Verzeichnis hat und wenn Sie ein Programm über die Shell ausführen, wird es in einem neuen Prozess ausgeführt. Die Standards "cd", "pushd" und "popd" sind in den Shell-Interpreter integriert, sodass sie den Shell-Prozess beeinflussen.

Indem Sie Ihr Programm zu einer Shell-Funktion machen, fügen Sie Ihren eigenen In-Process-Befehl hinzu, und jede Verzeichnisänderung wird im Shell-Prozess wiedergegeben.

winden
quelle
2
Wie würden Sie dies in tcsh tun?
Joedborg
4
+1. Eine Sache, die mir aufgefallen ist, war in der Datei, wir müssen die Funktion definieren, bevor wir sie aufrufen. Es könnte jemandem helfen, der so unerfahren ist wie ich.
Bhushan
Was ist der große Unterschied zwischen dem Definieren einer Funktion und dem Erstellen eines Alias?
HelloGoodbye
1
Wie führe ich das Skript aus, nachdem ich diese myprog.sh-Datei erstellt und zur .bashrc hinzugefügt habe? Soll ich meine Funktion aus einer anderen Shell-Datei oder direkt aus der Shell aufrufen? Es scheint, dass es in keiner Weise funktioniert ...
Andrea Silvestri
1
@AndreaSilvestri Entweder abmelden und wieder anmelden oder .bashrc als Quelle angeben. Das Hinzufügen zu .bashrc bewirkt nichts, bis .bashrc ausgeführt wird.
Jon Strayer
213

Wenn Sie Ihr Skript starten, wird ein neuer Prozess erstellt, der nur Ihre Umgebung erbt. Wenn es endet, endet es. Ihre aktuelle Umgebung bleibt wie sie ist.

Stattdessen können Sie Ihr Skript folgendermaßen starten:

. myscript.sh

Das .Skript wird in der aktuellen Umgebung ausgewertet, sodass es möglicherweise geändert wird

Norbert Hartl
quelle
4
+1 weil du recht hast. Obwohl ich aufrichtig bezweifle, dass er jedes Mal, wenn er es benötigt, ein Skript zum Ändern des Verzeichnisses erstellen möchte. Darüber hinaus sind .shErweiterungen völlig eww. Benutze sie nicht.
lhunath
1
Ja, normalerweise ist es besser, es nicht so zu verwenden. Meistens sind Sie froh, dass Ihre aktuelle Umgebung nicht leidet. Aber dann habe ich Skripte, um einige Setup-Aufgaben für mich zu erledigen, einschließlich des Wechsels an den richtigen Ort und dann ich. Sie auch. Übrigens. .sh ist natürlich eine Frage des persönlichen Stils. Ich würde es wahrscheinlich nicht verwenden, wenn ich Skripte systemweit installiere. Aber in meinem ~ / bin benutze ich sie, um zu wissen, was was ist :)
Norbert Hartl
11
@lhunath Warum sind .sh-Erweiterungen total eww?
Carl Pritchett
1
@CarlPritchett Befehlsnamenerweiterungen gelten als schädlich .
gniourf_gniourf
1
Für mich ist die Argumentation in diesem Artikel falsch. Es scheint, dass das Ergebnis im Voraus bekannt war, aber es war nicht so einfach, Gründe dafür zu finden. Ich bin der Meinung, dass es eine Frage des persönlichen Stils ist, sonst nichts.
Norbert Hartl
55

Angesichts der Unlesbarkeit und Überkomplikation von Antworten glaube ich, dass der Antragsteller dies tun sollte

  1. Fügen Sie dieses Skript zum hinzu PATH
  2. Führen Sie das Skript als aus . scriptname

Der .(Punkt) stellt sicher, dass das Skript nicht in einer untergeordneten Shell ausgeführt wird.

Steven Penny
quelle
38

Wenn Sie das Obige zusammenfügen, können Sie einen Alias ​​erstellen

alias your_cmd=". your_cmd"

wenn Sie nicht das führende "." Jedes Mal, wenn Sie Ihr Skript in die Shell-Umgebung einbinden möchten oder wenn Sie sich einfach nicht daran erinnern möchten, muss dies getan werden, damit das Skript ordnungsgemäß funktioniert.

MergerMan
quelle
Bleibt dies auch nach einem Neustart bestehen?
SDsolar
1
@SDsolar Sie müssen dies zu Ihrer ~ / .bashrc-Datei hinzufügen, um sie dauerhaft zu machen. Funktioniert wie ein Zauber für mich.
Rafał G.
Kann in ~ / .bash_aliases
Champ
@Champ ~/.bash_aliaseswird beim Start von Bash nicht immer bezogen.
Mateusz Piotrowski
31

Wenn Sie bash verwenden, können Sie Alias ​​versuchen:

Fügen Sie in die .bashrc-Datei diese Zeile ein:

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

Wenn Sie "p" in die Befehlszeile schreiben, wird das Verzeichnis geändert.

akarca
quelle
1
+1 für Alias. Die Shell-Funktion ist interessant, aber das OP hat nach einem einfachen Navi mit CD gefragt. Ich vermute, die meisten Leute brauchen ein Skript wie dieses, um in Quellcode-Zweigen zu navigieren, und dafür ist der Alias ​​ausreichend
Brad Dre
19

Wenn Sie ein Bash-Skript ausführen, wird es in der aktuellen Umgebung oder in den untergeordneten Umgebungen ausgeführt, niemals in der übergeordneten.

Wenn das Ziel darin besteht, Ihren Befehl auszuführen: goto.sh / home / test Dann arbeiten Sie interaktiv in / home / test. Eine Möglichkeit besteht darin, eine interaktive Bash-Subshell in Ihrem Skript auszuführen:

#!/bin/bash
cd $1
exec bash

Auf diese Weise befinden Sie sich in / home / test, bis Sie diese Shell verlassen (exit oder Strg + C).

philippe lhardy
quelle
Ich dachte, dies würde das Problem für ein Shell-Skript beheben, das ich ausführte, aber stattdessen wird die Shell gestartet und vergessen, was ich wollte.
Vwvan
13

Mit pushd wird das aktuelle Verzeichnis auf den Verzeichnisstapel verschoben und in das angegebene Verzeichnis geändert. Popd ruft das Verzeichnis oben auf dem Stapel ab und wechselt dann in dieses Verzeichnis.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
seb
quelle
2
Dies beantwortet meine Frage: Diese Lösung wird aktiv in einem S3-Init-Skript bereitgestellt und funktioniert einwandfrei. Danke @seb.
19h
5

Einfach gehen zu

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

und fügen Sie diesen Code neben der letzten Zeile hinzu:

alias yourcommand="cd /the_path_you_wish"

Beenden Sie dann den Editor.

Geben Sie dann Folgendes ein:

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

Jetzt können Sie Folgendes verwenden: Ihren Befehl im Terminal

ThangTD
quelle
3

Grundsätzlich kommen wir cd..aus jedem Verzeichnis zurück. Ich dachte, es einfacher zu machen, indem ich die Anzahl der Verzeichnisse angab, mit denen Sie gleichzeitig zurückkehren müssen. Sie können dies mithilfe des Alias-Befehls mithilfe einer separaten Skriptdatei implementieren. Beispielsweise:

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'   

Nach der Verwendung source code.shin der aktuellen Shell können Sie Folgendes verwenden:

$back 2 

zwei Schritte vom aktuellen Verzeichnis zurück zu kommen. Erklärt über im Detail hier . Dort wird auch erklärt, wie der Code in ~ / .bashrc eingefügt wird, damit jede neu geöffnete Shell automatisch diesen neuen Alias-Befehl erhält. Sie können einen neuen Befehl hinzufügen, um zu bestimmten Verzeichnissen zu gelangen, indem Sie den Code ändern, indem Sie weitere if conditionsund unterschiedliche Argumente hinzufügen . Sie können den Code auch hier von git abrufen .

Arun Chettoor
quelle
Gute
0

Dieser Ansatz ist für mich einfacher.

Angenommen, auf einem persönlichen iMac, auf dem Sie Administrator sind, befindet sich unter dem Standardverzeichnis beim Öffnen eines Befehlsfensters / Users / jdoe das Verzeichnis, in das Sie wechseln müssen: /Users/jdoe/Desktop/Mongo/db.3.2.1 /Behälter.

Dies sind die Schritte, mit denen die Arbeit erledigt werden kann:

  1. vi mongobin, in den ich eingetreten bin: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/binals erste Zeile.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!

Daniel C. Deng
quelle
0

Ich habe auch ein Dienstprogramm namens goat erstellt , das Sie zur einfacheren Navigation verwenden können.

Sie können den Quellcode auf GitHub anzeigen .

Ab Version 2.3.1 sieht die Nutzungsübersicht folgendermaßen aus:

# 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
quelle
0

Ich mache gerne dasselbe für verschiedene Projekte, ohne eine neue Shell zu starten.

In deinem Fall:

cd /home/artemb

Speichern Sie das Skript als:

echo cd /home/artemb

Dann starten Sie es mit:

\`./the_script\`

Dann gelangen Sie mit derselben Shell in das Verzeichnis.

DrGamma
quelle
0

Fügen Sie in Ihrem Shellscript Folgendes hinzu:

exec $SHELL
Alberto Corella
quelle
0

Erkläre deinen Weg:

PATH='/home/artemb'     
cd ${PATH}
m_sam
quelle
0

Schreiben Sie einfach PWDin Ihr Skript und exportieren Sie es, und die Änderung bleibt bestehen.

export PWD=/your/desired/directory
Samha '
quelle