Jak uzyskać aktualną nazwę katalogu roboczego w skrypcie bash, a jeszcze lepiej, po prostu polecenie terminalu.
pwdpodaje pełną ścieżkę bieżącego katalogu roboczego, np. /opt/local/binale chcę tylkobin
Jak uzyskać aktualną nazwę katalogu roboczego w skrypcie bash, a jeszcze lepiej, po prostu polecenie terminalu.
pwdpodaje pełną ścieżkę bieżącego katalogu roboczego, np. /opt/local/binale chcę tylkobin
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 :
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 /
$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.
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.
shi cshjeśli chciałeś klawisz Backspace do pracy trzeba było przeczytać całą sttystronę man, i podobało nam się to!”
Skorzystaj z basenameprogramu. W twoim przypadku:
% basename "$PWD"
bin
basenameprogramu? Co jest złego w tej odpowiedzi oprócz pominięcia cytatów?
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.
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ć.
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ą.
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?
$ echo "${PWD##*/}"
W pobliżu
echo "${PWD##*/}".
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).
Możesz użyć kombinacji pwd i basename. Na przykład
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
Co powiesz na grep:
pwd | grep -o '[^/]*$'
pwd | xargs basenamegdy nie .. prawdopodobnie nie jest tak ważny, ale druga odpowiedź jest prostsza i bardziej spójna w różnych środowiskach
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ć:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
Aby to zobaczyć, eksperyment:
cd foo
ln -s . bar
echo ${PWD##*/}
zgłasza „pasek”
Aby wyświetlić wiodące katalogi ścieżki (bez wywoływania fork-exec z / usr / bin / dirname):
echo ${target_PWD%/*}
To np. Przekształci foo / bar / baz -> foo / bar
readlink -fjest rozszerzeniem GNU, a zatem nie jest dostępne w BSD (w tym OS X).
echo "$PWD" | sed 's!.*/!!'
Jeśli używasz powłoki Bourne'a lub ${PWD##*/}nie jest dostępny.
${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.).
Zaskakujące, nikt nie wspomniał o tej alternatywie, która wykorzystuje tylko wbudowane polecenia bash:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
Jako dodatkowy bonus możesz łatwo uzyskać nazwę katalogu nadrzędnego za pomocą:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
Będą działać na Bash 4.3-alpha lub nowszym.
Posługiwać się:
basename "$PWD"
LUB
IFS=/
var=($PWD)
echo ${var[-1]}
Obróć wewnętrzny separator nazw plików (IFS) z powrotem do spacji.
IFS=
Po IFS jest jedna spacja.
basename $(pwd)
lub
echo "$(basename $(pwd))"
pwdjest dzielony na ciągi i rozwijany glob przed przekazaniem do basename.
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.
Aby znaleźć dżokejów takich jak ja:
find $PWD -maxdepth 0 -printf "%f\n"
$PWDaby "$PWD"poprawnie obsługiwać nietypowe nazwy katalogów.
zwykle używam tego w skryptach sh
SCRIPTSRC=`readlink -f "$0" || echo "$0"`
RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
echo "Running from ${RUN_PATH}"
...
cd ${RUN_PATH}/subfolder
możesz użyć tego do automatyzacji rzeczy ...
Działa również poniżej grep z regex,
>pwd | grep -o "\w*-*$"
Po prostu użyj:
pwd | xargs basename
lub
basename "`pwd`"
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.
Jeśli chcesz zobaczyć tylko bieżący katalog w obszarze monitu bash, możesz edytować .bashrcplik w ~. Zmień \wna \Ww linii:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
Uruchom source ~/.bashrci wyświetli nazwę katalogu tylko w obszarze monitu.
Patrz: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
Zdecydowanie wolę używać gbasename, który jest częścią jądra GNU.
basenametam nazywa . Jest to zwykle wywoływane tylko gbasenamena 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.
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$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.