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 /
Was ist der Unterschied zwischen $ {PWD ## * /} und $ PWD?
Mr_Chimp
24
@Mr_Chimp Ersteres ist eine Parametererweiterungsoperation, die den Rest des Verzeichnisses so trimmt, dass nur der Basisname angegeben wird. Ich habe in meiner Antwort einen Link zur Dokumentation zur Parametererweiterung. Fühlen Sie sich frei, dem zu folgen, wenn Sie Fragen haben.
Charles Duffy
24
@stefgosselin $PWDist 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.
Charles Duffy
5
Beachten Sie, dass die Ausgabe von aufgrund von Komplikationen durch symbolische Verknüpfungen pwdnicht 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. $PWDcd-o physical
Alex North-Keys
3
Nett! Jemand sollte ein Buch für alte Borne Shell-Typen wie mich schreiben. Vielleicht gibt es da draußen einen? Es könnte ein crotchity alt sys Sachen Admin sagen haben , wie „zurück in meinen Tag wir nur shund cshund wenn Sie die Rücktaste wollten Sie das Ganze lesen arbeiten musste sttyman - Seite, und wir hatten eine positive Erfahrung!“
Red Cricket
335
Verwenden Sie das basenameProgramm. Für Ihren Fall:
Ist das nicht der Zweck des basenameProgramms? Was ist falsch an dieser Antwort, außer dass die Anführungszeichen fehlen?
Nacht - Wiedereinstellung Monica
11
@Nacht basenameist 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.
Charles Duffy
3
... als Nebenbei bemerkt, meine Einwände gegen die basenamehier nicht gelten dirname, da dirnamehat Funktionen , die ${PWD##*/}nicht der Fall ist - eine Zeichenkette ohne Schrägstriche zu verwandeln ., zum Beispiel. Während die Verwendung dirnameals externes Tool einen Leistungsaufwand verursacht, verfügt es auch über Funktionen, die dazu beitragen, diese auszugleichen.
Charles Duffy
4
@ LouisMaddox, ein bisschen Kibitzing: Das functionSchlü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.
Charles Duffy
28
Sicher ist die Verwendung basenameweniger "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 basenamefunktioniert es genauso gut. Hat jemand jemals die "Leistung" eines Bash-Skripts verbessern und effizienter machen müssen?
@jocap ... außer dass die Verwendung von Echo dort, ohne das Argument zu zitieren, falsch ist . Wenn der Verzeichnisname mehrere Leerzeichen oder ein Tabulatorzeichen enthält, wird er auf ein einzelnes Leerzeichen reduziert. Wenn es ein Platzhalterzeichen hat, wird es erweitert. Richtige Verwendung wäre echo "${PWD##*/}".
Charles Duffy
9
@jocap ... außerdem bin ich mir nicht sicher, ob "Echo" tatsächlich ein legitimer Teil der Antwort ist. Die Frage war, wie man die Antwort bekommt , nicht wie man die Antwort druckt ; Wenn das Ziel beispielsweise darin bestand, es einer Variablen zuzuweisen, name=${PWD##*/}wäre dies richtig und name=$(echo "${PWD##*/}")falsch (im Sinne einer unnötigen Ineffizienz).
Charles Duffy
24
Sie können eine Kombination aus pwd und basename verwenden. Z.B
Bitte nicht. Die Backticks erstellen eine Subshell (also eine Gabeloperation) - und in diesem Fall verwenden Sie sie zweimal ! [Als zusätzliches, wenn auch stilistisches Problem sollten Variablennamen in Kleinbuchstaben geschrieben werden, es sei denn, Sie exportieren sie in die Umgebung oder es handelt sich um einen speziellen, reservierten Fall].
Charles Duffy
11
und als zweiter Stil sollten Quibble-Backtics durch $ () ersetzt werden. noch gabeln aber besser lesbar und mit weniger excaping benötigt.
Jeremy Wall
1
Konventionell werden Umgebungsvariablen (PATH, EDITOR, SHELL, ...) und interne Shell-Variablen (BASH_VERSION, RANDOM, ...) vollständig aktiviert. Alle anderen Variablennamen sollten klein geschrieben sein. Da bei Variablennamen zwischen Groß- und Kleinschreibung unterschieden wird, wird durch diese Konvention vermieden, dass Umgebungsvariablen und interne Variablen versehentlich überschrieben werden.
Rany Albeg Wein
2
Kommt auf die Konvention an. Man könnte argumentieren, dass alle Shell-Variablen Umgebungsvariablen sind (abhängig von der Shell), und daher sollten alle Shell-Variablen in Großbuchstaben angegeben werden. Jemand anderes könnte basierend auf dem Geltungsbereich argumentieren - globale Variablen sind Großbuchstaben, während lokale Variablen Kleinbuchstaben sind und diese alle global sind. Ein anderer könnte argumentieren, dass das Festlegen von Variablen in Großbuchstaben einen zusätzlichen Kontrast zu den Befehlen darstellt, die Shell-Skripte verunreinigen, bei denen es sich ebenfalls um kurze, aber aussagekräftige Kleinbuchstaben handelt. Ich kann einem dieser Argumente zustimmen oder auch nicht, aber ich habe alle drei in Gebrauch gesehen. :)
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:
Zu Ihrer Information, ${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).
Charles Duffy
1
Ja, ich habe ein altes Solaris-System verwendet. Ich habe den Befehl aktualisiert, um Anführungszeichen zu verwenden.
Anomalie
7
Dieser Thread ist großartig! Hier ist noch ein Geschmack:
überraschend? nur ein Scherz, aber andere sind viel kürzer und leichter zu merken
Codewandler
Das ist ziemlich lustig = P Hatte vorher noch nichts von $ IFS (internes Feldtrennzeichen) gehört. Meine Bash war zu alt, kann sie aber hier testen: jdoodle.com/test-bash-shell-script-online
Stan Kurdziel
5
Verwenden:
basename "$PWD"
ODER
IFS=/
var=($PWD)
echo ${var[-1]}
Schalten Sie den internen Dateinamen-Separator (IFS) wieder auf Leerzeichen.
Um korrekt zu sein, sind mehr Anführungszeichen pwderforderlich. Die Ausgabe von wird vor der Übergabe an Zeichenfolgen aufgeteilt und global erweitert basename.
Charles Duffy
Also 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.
Dies ist in jeder Hinsicht eine schlechtere Version der Antwort, die Arkady zuvor gegeben hat ( stackoverflow.com/a/1371267/14122 ): Die xargsFormulierung ist ineffizient und fehlerhaft, wenn Verzeichnisnamen wörtliche Zeilenumbrüche oder Anführungszeichen enthalten, und die zweite Formulierung ruft den pwdBefehl auf in einer Unterschale, anstatt dasselbe Ergebnis über eine integrierte variable Erweiterung abzurufen.
Charles Duffy
@ CharlesDuffy Trotzdem ist es eine gültige und praktische Antwort auf die Frage.
Bachph
1
Wenn Sie nur das aktuelle Verzeichnis in der Bash-Eingabeaufforderungsregion anzeigen möchten, können Sie die .bashrcDatei in bearbeiten ~. Ändern Sie \wzu \Win der Zeile:
Sie können das Dienstprogramm basename verwenden, mit dem alle Präfixe, die mit / enden, und das Suffix (falls in der Zeichenfolge vorhanden) aus der Zeichenfolge gelöscht und das Ergebnis in der Standardausgabe gedruckt werden.
Zu Ihrer Information, es kommt nicht mit meiner Ubuntu-Distribution.
Katastic Voyage
@ KatasticVoyage, es ist dort auf Ubuntu, es heißt nur basenamedort. Es wird normalerweise nur gbasenameunter MacOS und anderen Plattformen aufgerufen , die ansonsten mit einem Nicht-GNU-Basisnamen geliefert werden.
Charles Duffy
-1
Die folgenden Befehle führen dazu, dass Ihr aktuelles Arbeitsverzeichnis in einem Bash-Skript gedruckt wird.
(1) Ich bin nicht sicher, wo wir sicherstellen, dass die Argumentliste $1das aktuelle Arbeitsverzeichnis enthält. (2) Das pushdund hat popdhier 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.
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 :
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:Alternativ ohne
extglob
:quelle
$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 wirdpath/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
undcsh
und wenn Sie die Rücktaste wollten Sie das Ganze lesen arbeiten musstestty
man - Seite, und wir hatten eine positive Erfahrung!“Verwenden Sie das
basename
Programm. Für Ihren Fall:quelle
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 geltendirname
, dadirname
hat Funktionen , die${PWD##*/}
nicht der Fall ist - eine Zeichenkette ohne Schrägstriche zu verwandeln.
, zum Beispiel. Während die Verwendungdirname
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. Ansonstenbasename
funktioniert es genauso gut. Hat jemand jemals die "Leistung" eines Bash-Skripts verbessern und effizienter machen müssen?.
quelle
echo "${PWD##*/}"
.name=${PWD##*/}
wäre dies richtig undname=$(echo "${PWD##*/}")
falsch (im Sinne einer unnötigen Ineffizienz).Sie können eine Kombination aus pwd und basename verwenden. Z.B
quelle
Wie wäre es mit grep:
quelle
pwd | xargs basename
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:
Um dies zu sehen, ein Experiment:
meldet "bar"
DIRNAME
So zeigen Sie die führenden Verzeichnisse eines Pfads an (ohne dass ein Fork-Exec von / usr / bin / dirname erforderlich ist):
Dies wird zB foo / bar / baz -> foo / bar transformieren
quelle
readlink -f
handelt es sich um eine GNU-Erweiterung, die auf den BSDs (einschließlich OS X) nicht verfügbar ist.Wenn Sie die Bourne-Shell verwenden oder
${PWD##*/}
nicht verfügbar sind.quelle
${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).Dieser Thread ist großartig! Hier ist noch ein Geschmack:
quelle
Überraschenderweise erwähnte niemand diese Alternative, die nur eingebaute Bash-Befehle verwendet:
Als zusätzlichen Bonus können Sie den Namen des übergeordneten Verzeichnisses leicht erhalten mit:
Diese funktionieren unter Bash 4.3-alpha oder neuer.
quelle
Verwenden:
ODER
Schalten Sie den internen Dateinamen-Separator (IFS) wieder auf Leerzeichen.
Nach dem IFS steht ein Leerzeichen.
quelle
oder
quelle
pwd
erforderlich. Die Ausgabe von wird vor der Übergabe an Zeichenfolgen aufgeteilt und global erweitertbasename
.basename "$(pwd)"
- obwohl das im Vergleich zu just sehr ineffizient istbasename "$PWD"
, was selbst ineffizient ist im Vergleich zur Verwendung einer Parametererweiterung, anstatt überhaupt aufzurufenbasename
.Für die Findjockeys da draußen wie mich:
quelle
$PWD
in"$PWD"
, um ungewöhnliche Verzeichnisnamen korrekt zu behandeln.Ich benutze dies normalerweise in sh-Skripten
Sie können dies verwenden, um Dinge zu automatisieren ...
quelle
readlink: illegal option -- f usage: readlink [-n] [file ...]
Unten funktioniert grep with regex auch,
quelle
Benutz einfach:
oder
quelle
xargs
Formulierung ist ineffizient und fehlerhaft, wenn Verzeichnisnamen wörtliche Zeilenumbrüche oder Anführungszeichen enthalten, und die zweite Formulierung ruft denpwd
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: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
quelle
Sie können das Dienstprogramm basename verwenden, mit dem alle Präfixe, die mit / enden, und das Suffix (falls in der Zeichenfolge vorhanden) aus der Zeichenfolge gelöscht und das Ergebnis in der Standardausgabe gedruckt werden.
quelle
Ich bevorzuge stark die Verwendung
gbasename
, die Teil von GNU Coreutils ist.quelle
basename
dort. Es wird normalerweise nurgbasename
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.
quelle
$1
das aktuelle Arbeitsverzeichnis enthält. (2) Daspushd
und hatpopd
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.