Bash dizinini ve göreli yollarını bulmak için $ 0 değişkenini nasıl bölebilirim?


10

$ 0 değişkeni, komut dosyasının yol bilgilerini içerir.

  • Yol bilgisini mutlak yola nasıl değiştirebilirim? Yani, ~,., .. ya da benzeri nasıl işlenir?
  • Yol bilgisini dizin ve dosya adına nasıl bölebilirim?

Bunun için python / perl kullanabilirsiniz, ancak mümkünse bash kullanmak istiyorum.


ne elde etmeye çalışıyorsun? Btw. ~ / foo.sh ile bir betik çağırmak ~ bash sürümümle (GNU bash, sürüm 4.1.5 (2) -release- (x86_64-unknown-linux-gnu)) ana dizime ~ 0 $ genişleyecek
echox

Yanıtlar:


17

Gibi şeyleri işlemenize gerek yok ~, kabuk sizin için yapıyor. Bu yüzden ~/filenameherhangi bir komut dosyasına veya programa geçebilirsiniz ve çalışır - tüm bu programlar ~kendilerini işlemez , kabuğunuz argümanı dönüştürür ve /home/username/filenamebunun yerine programa aktarır:

$ echo ~/filename
/home/mrozekma/filename

Kurallı bir dosya adına (şunun gibi şeyler içermeyen bir dosyaya) ihtiyacınız varsa .., kullanın realpath(teşekkürler Neil ):

$ realpath ~/../filename
/home/filename

Bölünme dizin adı ve dosya adı, kullanıma yol gelince dirnameve basename:

$ dirname /foo/bar/baz
/foo/bar

$ basename /foo/bar/baz
baz

Bence realpath demek istiyorsun, readlink değil. readlink ortak durumda çalışmaz, yani bağlantı göreli bir yol kullandığında ve bağlantıyla aynı dizinde değilseniz.
Neil Mayhew

@Neil realpathdaha iyi, ama readlinkdenediğimde işe yarıyor gibi görünüyor; başarısız olduğu bir örnek biliyor musunuz?
Michael Mrozek

1
cd /tmp; touch foo; ln -s foo bar; cd; readlink /tmp/bar. Bu geri döner foove realpathgeri döner /tmp/foo.
Neil Mayhew

1
@Neil, @Michael: readlink -f(not -f) neredeyse eşdeğerdir realpathve daha taşınabilir: readlink -fGNU coreutils'de ve birkaç başka sistemde de bulunur; realpathayrı olarak paketlenir ve kurulmayabilir (örneğin, ortak olmayan 5 paket Ubuntu 10.04 veya Debian lenny'de buna bağlıdır).
Gilles 'SO- kötü olmayı bırak

@Gilles: iyi bir nokta. Realpath -f ile ilgili hatırlatma için teşekkürler.
Neil Mayhew

5

Michael tarafından belirtildiği gibi dirname ve basename kullanmak istediğinizi elde etmenin en güvenli yolu olmalıdır.

Her neyse, bunu "yalnızca bash araçlarıyla" gerçekten yapmak istiyorsanız parametre ikamesi kullanabilirsiniz:

echo `basename $PWD`        # Basename of current working directory.
echo "${PWD##*/}"           # Basename of current working directory.
echo
echo `basename $0`          # Name of script.
echo $0                     # Name of script.
echo "${0##*/}"             # Name of script.
echo
filename=test.data
echo "${filename##*.}"      # data
                            # Extension of filename.

Bu örnek doğrudan bir göz atmaya değer Gelişmiş Bash Komut Dosyası Kılavuzu'ndan alınır .

Açıklama oldukça basit:

$ {var # Pattern} $ var'ın $ var öğesinin ön ucuyla eşleşen en kısa kısmı var. $ {var ## Desen} $ var 'dan kaldır $ $' ın $ var 'ın ön ucuyla eşleşen en uzun kısmı.

Bazı regex gibi desen ve bak #ya ##açgözlü / olmayan açgözlü değiştirici çeşit olarak.

Bir yol parçasının bazı daha karmaşık çıkarımlarını yapmanız gerekecekse bu yararlı olabilir.


5
Kullanırken dikkat ${...##...}ve arkadaşlar ziyade dirnameve basenameonlar her durumda işe yaramaz. Örneğin hem ${0##*/}ve ${0%/*}aynı genişletmek $0eğer $0bir içermiyor /.
Gilles 'SO- kötü olmayı kes

@Gilles ${0%/*}, neden iyi bir alternatif olmadığını anlıyorum dirname. Ancak, ${0##*/}yerine kullanmakta yanlış olan ne basename?
toxalot 16:14

@toxalot Bunun için tek sorun, $0izleyen bir dizin adıdır /. Ama tavsiyeme pişmanım, çünkü dirnamedaha iyisini yapmıyor
Gilles 'SO- kötü olmayı kes'

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.