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.
Zauważ, że jeśli stosujesz tę technikę w innych okolicznościach (nie PWD, ale jakaś inna zmienna zawierająca nazwę katalogu), może być konieczne przycięcie końcowych ukośników. Poniżej używa obsługi extglob bash do pracy nawet z wieloma końcowymi ukośnikami:
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"
Alternatywnie bez extglob:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}"# remove everything before the last /
@Mr_Chimp to pierwsze jest operacją rozwijania parametrów, która przycina resztę katalogu, aby zapewnić tylko nazwę basename. Mam odpowiedź w dokumentacji dotyczącej rozszerzania parametrów; zachęcamy do śledzenia, jeśli masz jakieś pytania.
Charles Duffy,
24
@stefgosselin $PWDto nazwa wbudowanej zmiennej bash; wszystkie wbudowane nazwy zmiennych są pisane wielkimi literami (aby odróżnić je od zmiennych lokalnych, które zawsze powinny mieć co najmniej jedną małą literę). result=${PWD#*/}robi nie ocenia się /full/path/to/directory; zamiast tego usuwa tylko pierwszy element, czyniąc go path/to/directory; użycie dwóch #znaków sprawia, że wzór pasuje do zachłannego, dopasowując tyle znaków, ile się da. Przeczytaj stronę rozwijania parametrów, połączoną w odpowiedzi, aby uzyskać więcej.
Charles Duffy,
5
Zauważ, że wynik z pwdnie zawsze jest taki sam jak wartość $PWD, ze względu na komplikacje wynikające z wejścia cdprzez dowiązania symboliczne, czy bash ma -o physicalustawioną opcję i tak dalej. Kiedyś szczególnie nieprzyjemnie obchodziło się z obsługą katalogów montowanych automatycznie, gdzie rejestrowanie ścieżki fizycznej zamiast logicznej tworzyłoby ścieżkę, która, jeśli byłaby używana, pozwoliłaby automatycznemu spontanicznemu odinstalowaniu używanego katalogu.
Alex North-Keys
3
Miły! Ktoś powinien napisać książkę dla starych facetów z Borne, takich jak ja. Może jest tam jeden? To może mieć crotchity stare sys Admin mówiąc rzeczy jak „z powrotem w moich czasach mamy tylko shi cshjeśli chciałeś klawisz Backspace do pracy trzeba było przeczytać całą sttystronę man, i podobało nam się to!”
Czy to nie jest celem basenameprogramu? Co jest złego w tej odpowiedzi oprócz pominięcia cytatów?
Nacht - Przywróć Monikę
11
@Nacht basenamerzeczywiście jest zewnętrzny program, który robi to, co trzeba, ale działa żadnego zewnętrznego programu do bash, co można zrobić, out-of-the-box przy użyciu tylko wbudowaną funkcjonalność jest głupie, ponosząc wpływ na wydajność ( fork(), execve(), wait(), etc) dla bez powodu.
Charles Duffy
3
... na marginesie, moje zastrzeżenia do tego basenametutaj nie dotyczą dirname, ponieważ dirnamema funkcjonalność, która ${PWD##*/}tego nie robi - na przykład przekształcanie łańcucha bez ukośników .. Tak więc, chociaż korzystanie z niego dirnamejako narzędzia zewnętrznego ma narzut związany z wydajnością, ma również funkcjonalność, która pomaga to zrekompensować.
Charles Duffy,
4
@LouisMaddox, trochę kibitzowania: Słowo functionkluczowe jest niekompatybilne z POSIX- em bez dodawania wartości ponad standardową składnię, a brak cudzysłowów powodowałby błędy w nazwach katalogów ze spacjami. wdexec() { "./$(basename "$PWD")"; }może być preferowaną alternatywą.
Charles Duffy
28
Pewne użycie basenamejest mniej „wydajne”. Ale prawdopodobnie jest bardziej wydajny pod względem produktywności programistów, ponieważ jest łatwy do zapamiętania w porównaniu do brzydkiej składni bash. Więc jeśli to pamiętasz, idź. W przeciwnym razie basenamedziała równie dobrze. Czy ktoś kiedykolwiek musiał poprawić „wydajność” skryptu bash i uczynić go bardziej wydajnym?
@jocap ... poza tym, że użycie echa tam, bez cytowania argumentu, jest nieprawidłowe . Jeśli nazwa katalogu ma wiele spacji lub znak tabulacji, zostanie zwinięta do pojedynczej spacji; jeśli ma znak wieloznaczny, zostanie rozwinięty. Prawidłowe użycie byłoby echo "${PWD##*/}".
Charles Duffy,
9
@jocap ... też nie jestem pewien, czy „echo” jest w rzeczywistości uzasadnioną częścią odpowiedzi. Pytanie brzmiało: jak uzyskać odpowiedź, a nie jak wydrukować odpowiedź; jeśli celem name=${PWD##*/}byłoby na przykład przypisanie jej do zmiennej, byłoby to słuszne i name=$(echo "${PWD##*/}")błędne (w sensie niepotrzebnej nieefektywności).
Charles Duffy,
24
Możesz użyć kombinacji pwd i basename. Na przykład
Proszę nie. Backticks tworzą podpowłokę (czyli operację rozwidlenia) - w tym przypadku używasz ich dwa razy ! [Jako dodatkowy, aczkolwiek stylistyczny spór - nazwy zmiennych powinny być pisane małymi literami, chyba że eksportujesz je do środowiska lub są to specjalne, zastrzeżone przypadki].
Charles Duffy,
11
i jako drugi styl quibble backtics należy zastąpić $ (). wciąż widelce, ale bardziej czytelne i mniej potrzebne.
Jeremy Wall,
1
Zgodnie z konwencją zmienne środowiskowe (PATH, EDITOR, SHELL, ...) i wewnętrzne zmienne powłoki (BASH_VERSION, RANDOM, ...) są w pełni pisane wielkimi literami. Wszystkie pozostałe nazwy zmiennych powinny być pisane małymi literami. Ponieważ w nazwach zmiennych rozróżniana jest wielkość liter, konwencja ta pozwala uniknąć przypadkowego zastąpienia zmiennych środowiskowych i wewnętrznych.
Rany Albeg Wein 21.01.16
2
Zależy od konwencji. Można argumentować, że wszystkie zmienne powłoki są zmiennymi środowiskowymi (w zależności od powłoki), a zatem wszystkie zmienne powłoki powinny być pisane wielkimi literami. Ktoś inny mógłby się spierać w oparciu o zakres - zmienne globalne są wielkimi literami, podczas gdy zmienne lokalne są małymi literami i wszystkie są globalne. Jeszcze inny mógłby argumentować, że przekształcanie zmiennych na wielkie litery dodaje dodatkową warstwę kontrastu z poleceniami zaśmiecającymi skrypty powłoki, które są również małymi, ale znaczącymi słowami. Mogę, ale nie zgadzam się / z żadnym z tych argumentów, ale widziałem wszystkie trzy używane. :)
nie poleciłbym, ponieważ wydaje się, że dostaje trochę informacji o kolorze, podczas pwd | xargs basenamegdy nie .. prawdopodobnie nie jest tak ważny, ale druga odpowiedź jest prostsza i bardziej spójna w różnych środowiskach
davidhq
8
Podoba mi się wybrana odpowiedź (Charles Duffy), ale bądź ostrożny, jeśli jesteś w dowiązanym do siebie katalogu i chcesz nazwę docelowego katalogu. Niestety nie sądzę, że można tego dokonać w wyrażeniu rozwijającym jeden parametr, być może się mylę. To powinno działać:
FYI, ${PWD##*/}to POSIX sh - obsługuje każdy nowoczesny / bin / sh (w tym myślnik, popiół itp.); aby trafić do rzeczywistego Bourne'a na najnowszym pudełku, musisz być w nieco starszym systemie Solaris. Poza tym - echo "$PWD"; pominięcie cudzysłowu prowadzi do błędów (jeśli nazwa katalogu zawiera spacje, znaki wieloznaczne itp.).
Charles Duffy
1
Tak, korzystałem ze starego systemu Solaris. Zaktualizowałem polecenie, aby używać cudzysłowów.
zaskakująco? tylko żartuję, ale inne są znacznie krótsze i łatwiejsze do zapamiętania
programista
To dość zabawne = P Nie słyszałem wcześniej o $ IFS (separatorze pól wewnętrznych). mój bash był za stary, ale mogę go przetestować tutaj: jdoodle.com/test-bash-shell-script-online
Stan Kurdziel
5
Posługiwać się:
basename "$PWD"
LUB
IFS=/
var=($PWD)
echo ${var[-1]}
Obróć wewnętrzny separator nazw plików (IFS) z powrotem do spacji.
Potrzebuje więcej cytatów, aby były poprawne - w tej chwili wynik pwdjest dzielony na ciągi i rozwijany glob przed przekazaniem do basename.
Charles Duffy,
Tak więc basename "$(pwd)"- chociaż jest to bardzo nieefektywne w porównaniu do sprawiedliwego basename "$PWD", które samo w sobie jest nieefektywne w porównaniu do używania rozszerzenia parametrów zamiast wywoływania basenamew ogóle.
Jest to pod każdym względem gorsza wersja odpowiedzi poprzednio udzielonej przez Arkady'ego ( stackoverflow.com/a/1371267/14122 ): xargsFormuła jest nieefektywna i błędna, gdy nazwy katalogów zawierają dosłowne znaki nowej linii lub znaki cudzysłowu, a druga formuła wywołuje pwdpolecenie w podpowłoce zamiast pobierać ten sam wynik za pomocą wbudowanego rozszerzenia zmiennej.
Charles Duffy
@CharlesDuffy Niemniej jest to ważna i praktyczna odpowiedź na pytanie.
bachph
1
Jeśli chcesz zobaczyć tylko bieżący katalog w obszarze monitu bash, możesz edytować .bashrcplik w ~. Zmień \wna \Ww linii:
Możesz użyć narzędzia basename, które usuwa z łańcucha dowolny prefiks kończący się na / i sufiks (jeśli występuje w ciągu) i drukuje wynik na standardowym wyjściu.
Do Twojej wiadomości, nie pochodzi z moją dystrybucją Ubuntu.
Katastic Voyage
@KastasticVoyage, jest tam na Ubuntu, po prostu się basenametam nazywa . Jest to zwykle wywoływane tylko gbasenamena MacOS i innych platformach, które w przeciwnym razie są dostarczane z basenemame bez GNU.
Charles Duffy
-1
Następujące polecenia spowodują wydrukowanie bieżącego katalogu roboczego w skrypcie bash.
(1) Nie jestem pewien, gdzie upewniamy się, że lista argumentów $1zawiera bieżący katalog roboczy. (2) pushdI popdnie służą tutaj, ponieważ wszystko w backstikach odbywa się w podpowłoce - więc nie może wpływać na katalog powłoki nadrzędnej na początek. (3) Używanie "$(cd "$1"; pwd)"byłoby bardziej czytelne i odporne na nazwy katalogów z białymi znakami.
Odpowiedzi:
Nie ma potrzeby używania nazwy basename, a zwłaszcza podpowłoki z pwd (co dodaje dodatkową i kosztowną operację wideł ); powłoka może to zrobić wewnętrznie za pomocą rozszerzenia parametrów :
Zauważ, że jeśli stosujesz tę technikę w innych okolicznościach (nie
PWD
, ale jakaś inna zmienna zawierająca nazwę katalogu), może być konieczne przycięcie końcowych ukośników. Poniżej używa obsługi extglob bash do pracy nawet z wieloma końcowymi ukośnikami:Alternatywnie bez
extglob
:źródło
$PWD
to nazwa wbudowanej zmiennej bash; wszystkie wbudowane nazwy zmiennych są pisane wielkimi literami (aby odróżnić je od zmiennych lokalnych, które zawsze powinny mieć co najmniej jedną małą literę).result=${PWD#*/}
robi nie ocenia się/full/path/to/directory
; zamiast tego usuwa tylko pierwszy element, czyniąc gopath/to/directory
; użycie dwóch#
znaków sprawia, że wzór pasuje do zachłannego, dopasowując tyle znaków, ile się da. Przeczytaj stronę rozwijania parametrów, połączoną w odpowiedzi, aby uzyskać więcej.pwd
nie zawsze jest taki sam jak wartość$PWD
, ze względu na komplikacje wynikające z wejściacd
przez dowiązania symboliczne, czy bash ma-o physical
ustawioną opcję i tak dalej. Kiedyś szczególnie nieprzyjemnie obchodziło się z obsługą katalogów montowanych automatycznie, gdzie rejestrowanie ścieżki fizycznej zamiast logicznej tworzyłoby ścieżkę, która, jeśli byłaby używana, pozwoliłaby automatycznemu spontanicznemu odinstalowaniu używanego katalogu.sh
icsh
jeśli chciałeś klawisz Backspace do pracy trzeba było przeczytać całąstty
stronę man, i podobało nam się to!”Skorzystaj z
basename
programu. W twoim przypadku:źródło
basename
programu? Co jest złego w tej odpowiedzi oprócz pominięcia cytatów?basename
rzeczywiście jest zewnętrzny program, który robi to, co trzeba, ale działa żadnego zewnętrznego programu do bash, co można zrobić, out-of-the-box przy użyciu tylko wbudowaną funkcjonalność jest głupie, ponosząc wpływ na wydajność (fork()
,execve()
,wait()
, etc) dla bez powodu.basename
tutaj nie dotycządirname
, ponieważdirname
ma funkcjonalność, która${PWD##*/}
tego nie robi - na przykład przekształcanie łańcucha bez ukośników.
. Tak więc, chociaż korzystanie z niegodirname
jako narzędzia zewnętrznego ma narzut związany z wydajnością, ma również funkcjonalność, która pomaga to zrekompensować.function
kluczowe jest niekompatybilne z POSIX- em bez dodawania wartości ponad standardową składnię, a brak cudzysłowów powodowałby błędy w nazwach katalogów ze spacjami.wdexec() { "./$(basename "$PWD")"; }
może być preferowaną alternatywą.basename
jest mniej „wydajne”. Ale prawdopodobnie jest bardziej wydajny pod względem produktywności programistów, ponieważ jest łatwy do zapamiętania w porównaniu do brzydkiej składni bash. Więc jeśli to pamiętasz, idź. W przeciwnym raziebasename
działa równie dobrze. Czy ktoś kiedykolwiek musiał poprawić „wydajność” skryptu bash i uczynić go bardziej wydajnym?W pobliżu
źródło
echo "${PWD##*/}"
.name=${PWD##*/}
byłoby na przykład przypisanie jej do zmiennej, byłoby to słuszne iname=$(echo "${PWD##*/}")
błędne (w sensie niepotrzebnej nieefektywności).Możesz użyć kombinacji pwd i basename. Na przykład
źródło
Co powiesz na grep:
źródło
pwd | xargs basename
gdy nie .. prawdopodobnie nie jest tak ważny, ale druga odpowiedź jest prostsza i bardziej spójna w różnych środowiskachPodoba mi się wybrana odpowiedź (Charles Duffy), ale bądź ostrożny, jeśli jesteś w dowiązanym do siebie katalogu i chcesz nazwę docelowego katalogu. Niestety nie sądzę, że można tego dokonać w wyrażeniu rozwijającym jeden parametr, być może się mylę. To powinno działać:
Aby to zobaczyć, eksperyment:
zgłasza „pasek”
DIRNAME
Aby wyświetlić wiodące katalogi ścieżki (bez wywoływania fork-exec z / usr / bin / dirname):
To np. Przekształci foo / bar / baz -> foo / bar
źródło
readlink -f
jest rozszerzeniem GNU, a zatem nie jest dostępne w BSD (w tym OS X).Jeśli używasz powłoki Bourne'a lub
${PWD##*/}
nie jest dostępny.źródło
${PWD##*/}
to POSIX sh - obsługuje każdy nowoczesny / bin / sh (w tym myślnik, popiół itp.); aby trafić do rzeczywistego Bourne'a na najnowszym pudełku, musisz być w nieco starszym systemie Solaris. Poza tym -echo "$PWD"
; pominięcie cudzysłowu prowadzi do błędów (jeśli nazwa katalogu zawiera spacje, znaki wieloznaczne itp.).Ten wątek jest świetny! Oto jeszcze jeden smak:
źródło
Zaskakujące, nikt nie wspomniał o tej alternatywie, która wykorzystuje tylko wbudowane polecenia bash:
Jako dodatkowy bonus możesz łatwo uzyskać nazwę katalogu nadrzędnego za pomocą:
Będą działać na Bash 4.3-alpha lub nowszym.
źródło
Posługiwać się:
LUB
Obróć wewnętrzny separator nazw plików (IFS) z powrotem do spacji.
Po IFS jest jedna spacja.
źródło
lub
źródło
pwd
jest dzielony na ciągi i rozwijany glob przed przekazaniem dobasename
.basename "$(pwd)"
- chociaż jest to bardzo nieefektywne w porównaniu do sprawiedliwegobasename "$PWD"
, które samo w sobie jest nieefektywne w porównaniu do używania rozszerzenia parametrów zamiast wywoływaniabasename
w ogóle.Aby znaleźć dżokejów takich jak ja:
źródło
$PWD
aby"$PWD"
poprawnie obsługiwać nietypowe nazwy katalogów.zwykle używam tego w skryptach sh
możesz użyć tego do automatyzacji rzeczy ...
źródło
readlink: illegal option -- f usage: readlink [-n] [file ...]
Działa również poniżej grep z regex,
źródło
Po prostu użyj:
lub
źródło
xargs
Formuła jest nieefektywna i błędna, gdy nazwy katalogów zawierają dosłowne znaki nowej linii lub znaki cudzysłowu, a druga formuła wywołujepwd
polecenie w podpowłoce zamiast pobierać ten sam wynik za pomocą wbudowanego rozszerzenia zmiennej.Jeśli chcesz zobaczyć tylko bieżący katalog w obszarze monitu bash, możesz edytować
.bashrc
plik w~
. Zmień\w
na\W
w linii:Uruchom
source ~/.bashrc
i wyświetli nazwę katalogu tylko w obszarze monitu.Patrz: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
źródło
Możesz użyć narzędzia basename, które usuwa z łańcucha dowolny prefiks kończący się na / i sufiks (jeśli występuje w ciągu) i drukuje wynik na standardowym wyjściu.
źródło
Zdecydowanie wolę używać
gbasename
, który jest częścią jądra GNU.źródło
basename
tam nazywa . Jest to zwykle wywoływane tylkogbasename
na MacOS i innych platformach, które w przeciwnym razie są dostarczane z basenemame bez GNU.Następujące polecenia spowodują wydrukowanie bieżącego katalogu roboczego w skrypcie bash.
źródło
$1
zawiera bieżący katalog roboczy. (2)pushd
Ipopd
nie służą tutaj, ponieważ wszystko w backstikach odbywa się w podpowłoce - więc nie może wpływać na katalog powłoki nadrzędnej na początek. (3) Używanie"$(cd "$1"; pwd)"
byłoby bardziej czytelne i odporne na nazwy katalogów z białymi znakami.