Bir bash betiğinde yalnızca geçerli çalışma dizini adını veya daha da iyisi bir terminal komutunu nasıl alırım?
pwd
geçerli çalışma dizininin tam yolunu verir, örneğin /opt/local/bin
ama sadece istiyorumbin
Bir bash betiğinde yalnızca geçerli çalışma dizini adını veya daha da iyisi bir terminal komutunu nasıl alırım?
pwd
geçerli çalışma dizininin tam yolunu verir, örneğin /opt/local/bin
ama sadece istiyorumbin
Yanıtlar:
Basename gerekmiyor ve özellikle de bir subshell çalışan pwd'ye gerek yok ( ekstra ve pahalı bir çatal operasyonu ekliyor ); kabuk bunu parametre genişletme kullanarak dahili olarak yapabilir :
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.
Bu tekniği başka durumlarda uyguluyorsanız ( PWD
dizin adını taşıyan başka bir değişken değil , bazı değişkenler), sondaki eğik çizgileri kırpmanız gerekebileceğini unutmayın. Aşağıdakiler, birden fazla sondaki eğik çizgi ile bile çalışmak için bash'ın extglob desteğini kullanır :
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"
Alternatif olarak extglob
:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}" # remove everything before the last /
$PWD
yerleşik bir bash değişkeninin adıdır; tüm yerleşik değişken adları tamamen büyük harflidir (bunları her zaman en az bir küçük harf içermesi gereken yerel değişkenlerden ayırmak için). result=${PWD#*/}
does not etmek değerlendirmek /full/path/to/directory
; bunun yerine, yalnızca ilk öğeyi çıkarır path/to/directory
; iki #
karakter kullanmak , deseni olabildiğince çok karakterle eşleştirerek açgözlü eşleşmeyi sağlar. Daha fazla bilgi için cevaba bağlı parametre genişletme sayfasını okuyun.
pwd
her zaman değeriyle aynı olmadığını unutmayın . Bu, özellikle mantıksal yerine fiziksel yolun kaydedilmesinin, eğer kullanıldığında, otomatik sayacın kullanmakta olduğu dizini kendiliğinden çıkarmasına izin verecek bir yol üreteceği otomatik numaralandırılmış dizinlerin işlenmesi konusunda kötü olur. $PWD
cd
-o physical
sh
ve csh
siz bütün okumuştuk çalışmak için geri tuşunu istiyorsa ve stty
adam sayfası ve biz sevdim!"
basename
Programı kullanın . Davanız için:
% basename "$PWD"
bin
basename
programın amacı değil mi? Alıntıları kaçırmanın yanı sıra bu cevapta yanlış olan ne?
basename
gerçekten doğru şeyi yapmıyor harici bir program olmakla birlikte, çalışan herhangi bir şey partisi yüzünden harici program dışı-box yapabileceği tek yerleşik işlevlerini saçma kullanılarak, (performans etkisini ödemeden fork()
, execve()
, wait()
için, vs) sebep yok.
basename
buradaki itirazlarım geçerli değildirname
, çünkü dirname
işlevsel ${PWD##*/}
olmayan - eğik çizgi olmayan bir dizeyi dönüştürmek .
. Bu nedenle, dirname
harici bir araç olarak kullanılırken performans yükü vardır, aynı zamanda bunu telafi etmeye yardımcı olan işlevselliğe de sahiptir.
function
Anahtar kelime, standart sözdizimine herhangi bir değer katmadan POSIX ile uyumsuzdur ve tırnak işaretleri boşluk içeren dizin adlarında hatalar oluşturur. wdexec() { "./$(basename "$PWD")"; }
tercih edilebilir bir alternatif olabilir.
basename
kullanım daha az "verimli". Ancak , geliştirici verimliliği açısından muhtemelen daha verimlidir, çünkü çirkin bash sözdizimine kıyasla hatırlanması kolaydır. Eğer hatırlarsanız, devam edin. Aksi takdirde, aynı şekilde basename
çalışır. Herkes bir bash betiğinin "performansını" geliştirmek ve daha verimli hale getirmek zorunda mıydı?
$ echo "${PWD##*/}"
echo "${PWD##*/}"
.
name=${PWD##*/}
olsaydı, doğru name=$(echo "${PWD##*/}")
olur ve yanlış olur (gereksiz verimsiz anlamda).
Pwd ve basename kombinasyonunu kullanabilirsiniz. Örneğin
#!/bin/bash
CURRENT=`pwd`
BASENAME=`basename "$CURRENT"`
echo "$BASENAME"
exit;
Seçilen cevabı seviyorum (Charles Duffy), ancak işaretlenmiş bir direkte iseniz ve hedef dir ismini istiyorsanız dikkatli olun. Ne yazık ki tek bir parametre genişletme ifadesinde yapılabileceğini sanmıyorum, belki yanılıyorum. Bu çalışmalı:
target_PWD=$(readlink -f .)
echo ${target_PWD##*/}
Bunu görmek için bir deneme:
cd foo
ln -s . bar
echo ${PWD##*/}
raporlar "çubuk"
Bir yolun önde gelen dizinlerini göstermek için (/ usr / bin / dirname öğesinin fork-exec işlemine gerek kalmadan):
echo ${target_PWD%/*}
Bu, örneğin foo / bar / baz -> foo / bar'ı dönüştürür
readlink -f
bir GNU uzantısıdır ve bu nedenle BSD'lerde (OS X dahil) mevcut değildir.
echo "$PWD" | sed 's!.*/!!'
Bourne kabuğu kullanıyorsanız veya ${PWD##*/}
kullanılamıyorsa.
${PWD##*/}
POSIX sh - her modern / bin / sh (çizgi, kül vb. Dahil) bunu destekler; yeni bir kutuda gerçek Bourne vurmak için, hafif eski bir Solaris sisteminde olmanız gerekir. Bunun ötesinde - echo "$PWD"
; tırnak işaretlerini bırakmak hatalara yol açar (dizin adında boşluklar, joker karakterler vb. varsa).
Şaşırtıcı bir şekilde, hiç kimse sadece yerleşik bash komutlarını kullanan bu alternatiften bahsetmedi:
i="$IFS";IFS='/';set -f;p=($PWD);set +f;IFS="$i";echo "${p[-1]}"
Ek bir bonus olarak, ana dizinin adını aşağıdakilerle kolayca elde edebilirsiniz:
[ "${#p[@]}" -gt 1 ] && echo "${p[-2]}"
Bunlar Bash 4.3-alfa veya daha yenisi üzerinde çalışır.
kullanın:
basename "$PWD"
VEYA
IFS=/
var=($PWD)
echo ${var[-1]}
Dahili Dosya Adı Ayırıcısını (IFS) tekrar boşluğa çevirin.
IFS=
IFS'den sonra bir boşluk var.
basename $(pwd)
veya
echo "$(basename $(pwd))"
pwd
aktarılmadan önce dize bölünmüş ve glob genişletilmiş basename
.
basename "$(pwd)"
- bu sadece göre çok verimsiz olsa basename "$PWD"
, hangi kendisi bir parametre açılımı kullanılarak yerine çağırarak kıyasla verimsiz basename
hiç.
Orada benim gibi jokeyleri bulmak için:
find $PWD -maxdepth 0 -printf "%f\n"
$PWD
için "$PWD"
olarak değiştirin .
bunu genellikle sh betiklerinde kullanırım
SCRIPTSRC=`readlink -f "$0" || echo "$0"`
RUN_PATH=`dirname "${SCRIPTSRC}" || echo .`
echo "Running from ${RUN_PATH}"
...
cd ${RUN_PATH}/subfolder
bunu otomatikleştirmek için kullanabilirsiniz ...
Regex ile grep'in altında da çalışıyor,
>pwd | grep -o "\w*-*$"
Sadece kullan:
pwd | xargs basename
veya
basename "`pwd`"
xargs
Dizin adları değişmez yeni satırlar veya alıntı karakterler içerdiğinde ve ikinci formülasyon pwd
komutu çağırdığında formül yetersiz ve buggy yerleşik bir değişken genişletme yoluyla aynı sonucu almak yerine, bir alt kabukta.
Bash istemi bölgesinde yalnızca geçerli dizini görmek istiyorsanız, .bashrc
dosyayı düzenleyebilirsiniz ~
. Değişim \w
için \W
doğrultusunda:
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
Çalıştır source ~/.bashrc
ve yalnızca bilgi istemi bölgesinde dizin adını görüntüler.
Ref: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
gbasename
GNU coreutils'in bir parçası olan kullanmayı tercih ederim .
basename
orada deniyor . Yalnızca gbasename
MacOS ve diğer platformlarda denir , aksi takdirde GNU olmayan bir temel adla birlikte gönderilir.
Aşağıdaki komutlar, geçerli çalışma dizininizi bash komut dosyasında yazdırmanıza neden olur.
pushd .
CURRENT_DIR="`cd $1; pwd`"
popd
echo $CURRENT_DIR
$1
geçerli çalışma dizinini içerecek şekilde olmasını sağladığımızdan emin değilim . (2) pushd
ve popd
burada hiçbir amaca hizmet etmez, çünkü backticks içindeki herhangi bir şey bir alt kabukta yapılır - bu nedenle başlangıçta üst kabuğun dizinini etkileyemez. (3) "$(cd "$1"; pwd)"
Boşluklu dizin adlarına karşı kullanmak hem daha okunabilir hem de daha dayanıklı olur.