Wie würde ich nur den aktuellen Arbeitsverzeichnisnamen in einem Bash-Skript oder noch besser nur einen Terminalbefehl erhalten?
pwd
gibt den vollständigen Pfad des aktuellen Arbeitsverzeichnisses an, zB /opt/local/bin
aber ich will nurbin
Wie würde ich nur den aktuellen Arbeitsverzeichnisnamen in einem Bash-Skript oder noch besser nur einen Terminalbefehl erhalten?
pwd
gibt den vollständigen Pfad des aktuellen Arbeitsverzeichnisses an, zB /opt/local/bin
aber ich will nurbin
Antworten:
Keine Notwendigkeit für einen Basisnamen und insbesondere keine Notwendigkeit für eine Unterschale, auf der pwd ausgeführt wird (was eine zusätzliche und teure Gabeloperation hinzufügt ); Die Shell kann dies intern mithilfe der Parametererweiterung tun :
result=${PWD##*/} # to assign to a variable
printf '%s\n' "${PWD##*/}" # to print to stdout
# ...more robust than echo for unusual names
# (consider a directory named -e or -n)
printf '%q\n' "${PWD##*/}" # to print to stdout, quoted for use as shell input
# ...useful to make hidden characters readable.
Beachten Sie, dass Sie, wenn Sie diese Technik unter anderen Umständen anwenden (nicht PWD
, sondern bei einer anderen Variablen, die einen Verzeichnisnamen enthält), möglicherweise nachfolgende Schrägstriche kürzen müssen. Im Folgenden wird die Extglob-Unterstützung von bash verwendet , um auch mit mehreren nachgestellten Schrägstrichen zu arbeiten:
dirname=/path/to/somewhere//
shopt -s extglob # enable +(...) glob syntax
result=${dirname%%+(/)} # trim however many trailing slashes exist
result=${result##*/} # remove everything before the last / that still remains
printf '%s\n' "$result"
Alternativ ohne extglob
:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}" # remove everything before the last /
$PWD
ist der Name einer integrierten Bash-Variablen. Alle integrierten Variablennamen sind in Großbuchstaben angegeben (um sie von lokalen Variablen zu unterscheiden, die immer mindestens ein Kleinbuchstaben haben sollten). result=${PWD#*/}
tut nicht bewerten zu /full/path/to/directory
; Stattdessen wird nur das erste Element entfernt, wodurch es erstellt wird path/to/directory
. Wenn Sie zwei #
Zeichen verwenden, wird das Muster gierig und es werden so viele Zeichen wie möglich angezeigt. Weitere Informationen finden Sie auf der Seite zur Parametererweiterung, die in der Antwort verlinkt ist.
pwd
nicht immer mit dem Wert von übereinstimmt , ob für bash die Option festgelegt ist usw. Dies war früher besonders unangenehm bei der Handhabung von Verzeichnissen mit automatischer Bereitstellung, bei denen das Aufzeichnen des physischen Pfads anstelle des logischen Pfads einen Pfad ergab, der es dem automatischen Zähler bei Verwendung ermöglichte, das verwendete Verzeichnis spontan zu entfernen. $PWD
cd
-o physical
sh
und csh
und wenn Sie die Rücktaste wollten Sie das Ganze lesen arbeiten musste stty
man - Seite, und wir hatten eine positive Erfahrung!“
Verwenden Sie das basename
Programm. Für Ihren Fall:
% basename "$PWD"
bin
basename
Programms? Was ist falsch an dieser Antwort, außer dass die Anführungszeichen fehlen?
basename
ist in der Tat ein externes Programm , das das Richtige tut, sondern läuft jede für eine Sache bash kann externes Programm tun out-of-the-Box mit nur integrierte Funktionalität albern ist, Auswirkungen auf die Leistung entstehen ( fork()
, execve()
, wait()
, usw.) für kein Grund.
basename
hier nicht gelten dirname
, da dirname
hat Funktionen , die ${PWD##*/}
nicht der Fall ist - eine Zeichenkette ohne Schrägstriche zu verwandeln .
, zum Beispiel. Während die Verwendung dirname
als externes Tool einen Leistungsaufwand verursacht, verfügt es auch über Funktionen, die dazu beitragen, diese auszugleichen.
function
Schlüsselwort ist POSIX-inkompatibel, ohne einen Wert gegenüber der standardisierten Syntax hinzuzufügen, und das Fehlen von Anführungszeichen würde Fehler in Verzeichnisnamen mit Leerzeichen verursachen. wdexec() { "./$(basename "$PWD")"; }
könnte eine bevorzugte Alternative sein.
basename
weniger "effizient". Aber es ist wahrscheinlich mehr effizienter in Bezug auf die Produktivität der Entwickler , weil es einfach ist , im Vergleich zu erinnern an die hässliche bash Syntax. Also, wenn Sie sich daran erinnern, machen Sie es. Ansonsten basename
funktioniert es genauso gut. Hat jemand jemals die "Leistung" eines Bash-Skripts verbessern und effizienter machen müssen?
$ echo "${PWD##*/}"
.
echo "${PWD##*/}"
.
name=${PWD##*/}
wäre dies richtig und name=$(echo "${PWD##*/}")
falsch (im Sinne einer unnötigen Ineffizienz).
Sie können eine Kombination aus pwd und basename verwenden. Z.B
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
Ich mag die ausgewählte Antwort (Charles Duffy), aber seien Sie vorsichtig, wenn Sie sich in einem verknüpften Verzeichnis befinden und den Namen des Zielverzeichnisses möchten. Leider glaube ich nicht, dass dies in einem einzelnen Parametererweiterungsausdruck möglich ist, vielleicht irre ich mich. Das sollte funktionieren:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
Um dies zu sehen, ein Experiment:
cd foo
ln -s . bar
echo ${PWD##*/}
meldet "bar"
So zeigen Sie die führenden Verzeichnisse eines Pfads an (ohne dass ein Fork-Exec von / usr / bin / dirname erforderlich ist):
echo ${target_PWD%/*}
Dies wird zB foo / bar / baz -> foo / bar transformieren
readlink -f
handelt es sich um eine GNU-Erweiterung, die auf den BSDs (einschließlich OS X) nicht verfügbar ist.
echo "$PWD" | sed 's!.*/!!'
Wenn Sie die Bourne-Shell verwenden oder ${PWD##*/}
nicht verfügbar sind.
${PWD##*/}
ist POSIX sh - jedes moderne / bin / sh (einschließlich Armaturenbrett, Asche usw.) unterstützt es; Um Bourne auf einer aktuellen Box zu treffen, müssen Sie sich auf einem leicht veralteten Solaris-System befinden. Darüber hinaus - echo "$PWD"
; Das Weglassen der Anführungszeichen führt zu Fehlern (wenn der Verzeichnisname Leerzeichen, Platzhalterzeichen usw. enthält).
Überraschenderweise erwähnte niemand diese Alternative, die nur eingebaute Bash-Befehle verwendet:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
Als zusätzlichen Bonus können Sie den Namen des übergeordneten Verzeichnisses leicht erhalten mit:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
Diese funktionieren unter Bash 4.3-alpha oder neuer.
Verwenden:
basename "$PWD"
ODER
IFS=/
var=($PWD)
echo ${var[-1]}
Schalten Sie den internen Dateinamen-Separator (IFS) wieder auf Leerzeichen.
IFS=
Nach dem IFS steht ein Leerzeichen.
basename $(pwd)
oder
echo "$(basename $(pwd))"
pwd
erforderlich. Die Ausgabe von wird vor der Übergabe an Zeichenfolgen aufgeteilt und global erweitert basename
.
basename "$(pwd)"
- obwohl das im Vergleich zu just sehr ineffizient ist basename "$PWD"
, was selbst ineffizient ist im Vergleich zur Verwendung einer Parametererweiterung, anstatt überhaupt aufzurufen basename
.
Für die Findjockeys da draußen wie mich:
find $PWD -maxdepth 0 -printf "%f\n"
$PWD
in "$PWD"
, um ungewöhnliche Verzeichnisnamen korrekt zu behandeln.
Ich benutze dies normalerweise in sh-Skripten
SCRIPTSRC=`readlink -f "$0" || echo "$0"`
RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
echo "Running from ${RUN_PATH}"
...
cd ${RUN_PATH}/subfolder
Sie können dies verwenden, um Dinge zu automatisieren ...
Unten funktioniert grep with regex auch,
>pwd | grep -o "\w*-*$"
Benutz einfach:
pwd | xargs basename
oder
basename "`pwd`"
xargs
Formulierung ist ineffizient und fehlerhaft, wenn Verzeichnisnamen wörtliche Zeilenumbrüche oder Anführungszeichen enthalten, und die zweite Formulierung ruft den pwd
Befehl auf in einer Unterschale, anstatt dasselbe Ergebnis über eine integrierte variable Erweiterung abzurufen.
Wenn Sie nur das aktuelle Verzeichnis in der Bash-Eingabeaufforderungsregion anzeigen möchten, können Sie die .bashrc
Datei in bearbeiten ~
. Ändern Sie \w
zu \W
in der Zeile:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
Ausführen source ~/.bashrc
und es wird nur der Verzeichnisname in der Eingabeaufforderungsregion angezeigt.
Ref: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
Ich bevorzuge stark die Verwendung gbasename
, die Teil von GNU Coreutils ist.
basename
dort. Es wird normalerweise nur gbasename
unter MacOS und anderen Plattformen aufgerufen , die ansonsten mit einem Nicht-GNU-Basisnamen geliefert werden.
Die folgenden Befehle führen dazu, dass Ihr aktuelles Arbeitsverzeichnis in einem Bash-Skript gedruckt wird.
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$1
das aktuelle Arbeitsverzeichnis enthält. (2) Das pushd
und hat popd
hier keinen Zweck, da alles in Backticks in einer Subshell ausgeführt wird - es kann also zunächst keinen Einfluss auf das Verzeichnis der übergeordneten Shell haben. (3) Die Verwendung "$(cd "$1"; pwd)"
wäre sowohl lesbar als auch widerstandsfähiger gegenüber Verzeichnisnamen mit Leerzeichen.