Bir komut dosyasından mutlak yol bulma


10

Bir komut dosyasında $0olası göreli yoldan geçiyorum. Mutlak hale getirmek için anlamadığım bu çözümü buldum:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

Benim sorunum ${0%/*}ve içindeki sihir ${0##*/}. Görünüşe göre eski dirname adını alır ve ikincisi dosya adını çıkarır, nasıl olduğunu anlamıyorum.


2
Bu parametre genişletmeyi kullanır, ancak benim için çalışmadı. Betiğiniz yalnızca Linux'ta kullanılacaksa readlink -f $0, kurallı yolu elde etmek için kullanabilirsiniz .
Shawn J. Goff

1
@Shawn: Doğru düşünceyi sunduğunuz için 1 harika yorum oyu: "Bu, parametre genişletmeyi kullanır, ancak benim için çalışmadı". dirnameUtil burada yararlıdır.
D4RIO

mywiki.wooledge.org/BashFAQ/028 ve cyberciti.biz/faq/... diyor BASH_SOURCEdaha iyi olduğu $0gibi $0kullanıcı komutası yazdığınız, şu anda yürütülen komut dosyası olmayabilir hangi verir.
Joel Purra

Yanıtlar:


8

Tanımlar:

${string%substring}$substringsonuna kadar olan en kısa eşleşmeyi siler $string.

${string##substring}en uzun eşleşmesini $substringen başından siler $string.

Örneğiniz:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

${0%/*} son eğik çizgiden sonra her şeyi silerek komut dosyasının dizin adını verir (göreceli bir yol olabilir).

${0##*/} her şeyi son eğik çizgiye kadar siler ve size komut dosyasının adını verir.

Bu nedenle, bu komut komut dosyasının dizinine dönüşür ve geçerli çalışma dizinini (tarafından verilen $PWD) ve komut dosyasının adını size mutlak yolu veren bir araya getirir.

Neler olup bittiğini görmek için şunu deneyin:

echo ${0%/*}
echo ${0##*/}

Kabuk özel karakterleri içeren (neredeyse tümü) dosya adlarıyla başa çıkmak için tüm değişken genişletmelerin etrafına çift tırnak ekleyin.
Gilles 'SO- kötü olmayı bırak'

10

En basit çözüme sahipti readlink -f $0. Garip dosya adlarını işlemek için kesinlikle emin olmak istiyorsanız, bunu kullanabilirsiniz:

absolute_path_x="$(readlink -fn -- "$0"; echo x)"
absolute_path="${absolute_path_x%x}"

belgeleme


1
Son satırların doğru bir şekilde ele alındığını görmek güzel. Ne yazık ki readlink -fnLinux, NetBSD ve OpenBSD'ye özgüdür.
Gilles 'SO- kötü olmayı bırak'

4

İşte bu işi yapmanın daha güvenli ve daha okunaklı bir yolu:

abspath=$(unset CDPATH && cd "$(dirname "$0")" && echo $PWD/$(basename "$0"))

Notlar:

  • Eğer $0hiçbir önceki yol olmayan bir çıplak dosya adı, özgün senaryo başarısız olur ama burada verilen bir çalışacaktır. (Sorun değil $0ancak diğer uygulamalarda da olabilir.)
  • Dosya yolu gerçekten yoksa, her iki yaklaşım da başarısız olur. (Sorun değil $0, diğer uygulamalarda olabilir.)
  • unsetKullanıcı olabilir eğer esastır CDPATHayarlayın.
  • Aksine readlink -fveya realpathbu (örneğin Mac OS X) Unix olmayan Linux versiyonları üzerinde çalışacak.

2

Eğer Kabuk Parametrelerinin öğrenmek istiyorsanız, onu okuyabilir burada ama Genişleme her zaman iyi bir seçim değildir. Bu durumda, hemen hemen her Unix benzeri sistemin 2 iyi kullanımı vardır:

basename
dirname

Birincisi dosya adını çıkarırken, ikincisi yolu çıkarır, bu nedenle, 0 $ varsa, söyle:

dirname $0

Ve yolu alacaksın.

Şerefe


dirname göreli yollar döndürebilir
optik

0

Pwd, bash yerleşkesi ile tanışın. Ayrıca GNU coreutils paketinde bulunur.

$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd `dirname "$0"` ; pwd -P)
absBin=$( cd `dirname "$0"` ; /bin/pwd -P)
echo \$0: $0
echo cheeky binary from $abs \($absBin\)
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.