Bash'de dosya yolu bağımsız değişkeninde son dirname / dosya adını alın


228

Geliştirme sunucumuzda barındırılan SVN için bir post-taahhüt kanca yazmaya çalışıyorum. Amacım, taahhüt edilen projenin bir kopyasını sunucuda barındırıldığı dizine otomatik olarak teslim etmeye çalışmaktır. Ancak, projelerimizin barındırıldığı aynı alt dizine ödeme yapmak için komut dosyasına geçirilen dizin dizesindeki yalnızca son dizini okuyabilmem gerekiyor.

Örneğin, bir SVN projesine "example" projesini uygularsam, komut dosyam ilk argümanı olarak "/ usr / local / svn / repos / example" alır. Ben sadece "örnek" dize sonuna almak ve sonra "/ server / root / example" için ödeme ve değişiklikleri hemen canlı görmek böylece başka bir dize ile concat gerekir.

Yanıtlar:


345

basename yolun dizin önekini kaldırır:

$ basename /usr/local/svn/repos/example
example
$ echo "/server/root/$(basename /usr/local/svn/repos/example)"
/server/root/example

2
basename kesinlikle aradığım şey. Bir değişkenin içinde saklanan bir argümanın taban adını nasıl alabilirim? Ör.SUBDIR="/path/to/whatever/$(basename $1)"
TJ L

5
@ tj111: sesler hayır $1gibi veya $1boş
sth

ne yazık ki, komutları sararsanız, basename iyi bir fikir değildir. akılda tutulması gereken bir şey
dtc

99

Bir yol adının herhangi bir yolunu elde etmek için aşağıdaki yaklaşım kullanılabilir:

some_path=a/b/c
echo $(basename $some_path)
echo $(basename $(dirname $some_path))
echo $(basename $(dirname $(dirname $some_path)))

Çıktı:

c
b
a

1
boşlukları olan yollarla çalışmaz ... tırnak ile bunu aşabilirsiniz ... bir şekilde çalışırecho "$(basename "$(dirname "$pathname")")"
Ray Foss

75

Bash, dış yolu çağırmak zorunda kalmadan bir yolun son bölümünü alabilir basename:

subdir="/path/to/whatever/${1##*/}"

2
Mac bilgisayarımda, birkaç bin dosyanın her biri için önemsiz bir şey yaptığınız durumda, alt dize notasyonunu kullanmak, büyüklük sırasından daha hızlıdır.
George

1
d=/home/me/somefolder;subdir="/$d/${1##*/}"Ben //home/me/somefolder//$ d aslında bir döngü geliyor gibi bir şey ile sona erdi for d in $(find $SOMEFOLDER -maxdepth 1 -type d);kullanarak subdir=$(basename $d)beklendiği gibi çalışır.
Buttle Butkus

1
@ButtleButkus: Çıktısını yinelemek ( daha iyi) veya globbing kullanmak whileyerine kullanmalısınız: (son eğik çizgi şöyle çalışır - eğer yinelemek için Bash 4'te kullanabilirsiniz , ancak bir "Bağımsız değişken listesi çok uzun" mesajı mümkün). Komutun bir komut dosyasının veya işlevin ilk bağımsız değişkenini temsil ettiğini unutmayın . Başka bir değişken veya bağımsız değişken belirtimi kullanmanız veya bir bağımsız değişkenin iletildiğinden emin olmanız gerekebilirforfindfind -print0 | xargs -0for d in $SOMEFOLDER/*/-type d**shopt -s globstar${1}${d##*/}$1
sonraki bildirime kadar duraklatıldı.

2
@DennisWilliamson Teşekkür için çok paylaşımı . Neden işe yaramadığını merak eden gelecekteki okuyucular için ya da ben burada sadece aptalım am . Yukarıdaki yanıtın $1içerdiği varsayılmaktadır the path from which last component is to be taken out. O kısmı kaçırdım. Benim kullanım durumum: target_path='/home/user/dir1/dir2/dir3/'; target_path="${target_path%/}"; last_component=${target_path##*/}; echo $last_component- Çalışmalar 😉
Vinay Vissh

2
Nasıl ve neden ${1##*/} çalıştığına dair bir açıklama için buraya bakın : unix.stackexchange.com/a/171786/15070
Matthew
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.