$ PATH içinde bulunan aynı betiğin altındaki bir dosyaya bakın


33

Komut dosyasını herhangi bir dizinden çağırabilmem için $ PATH öğesine eklenen bir dizinin altına yerleştirilen bir bash komut dosyasına sahibim.

Komut dosyasıyla aynı dizinin altında başka bir metin dosyası var. Senaryoda metin dosyasına nasıl başvurulur acaba?

Örneğin, komut dosyası yalnızca metin dosyasının içeriğini cat textfileçıkartacaksa, komut dosyasını farklı bir dizinden çağırırken çalışmaz, çünkü metin dosyası bulunmaz.



Bu soru nasıl bir bash betiği dosya yolunu güvenli bir şekilde alabileceğimi gösterir, bunu yoluma ekledim: stackoverflow.com/q/4774054/1695680
ThorSummoner

Yanıtlar:


24

Bunlar, hiçbir sembolik bağlantı olmadığı sürece (yol genişlemesinde veya betiğin kendisinde) aynı şekilde çalışmalıdır:

  • MYDIR="$(dirname "$(realpath "$0")")"

  • MYDIR="$(dirname "$(which "$0")")"

  • Yukarıdakilerden herhangi birinin iki aşamalı versiyonu:

    MYSELF="$(realpath "$0")"

    MYDIR="${MYSELF%/*}"

Komut dosyanızın yolunda bir işaret varsa, o whichzaman bu bağlantının çözümünü içermeyen bir cevap verecektir. realpathSisteminizde varsayılan olarak kurulu değilse , burada bulabilirsiniz .

[EDIT]: Caleb'in önerdiğinden daha realpathfazla avantajı olmadığı anlaşılıyorsa , sonuncusunu kullanmak daha iyi olacaktır. Zamanlama testlerim aslında daha hızlı olduğunu gösteriyor.readlink -f


Sorun değil. Bu arada realpathsisteminizde nereden geliyor? (Sahip olmayanlar için kullanabilirsinizreadlink -f
Caleb

@Caleb Aslında bunun standart GNU yardımcı programlarına (coreutils) ait olduğunu düşündüm, ama şimdi bunun ayrı bir paket olduğunu görebiliyorum .
rozcietrzewiacz

@ rozcietrzewiacz realpath, daha önceleri readlink -f(ve hatta readlinkIIRC) GNU coreutils'deydi (çevresinde benzer birçok araç vardı. readlink -fSonunda fiili standart oldu); realpathsadece onu hala kullanan betiklerle uyumluluk için tutulur.
Gilles 'SO- kötülük' dur

Nedir avantajı $(dirname "$(which "$0")")üzerinde $(dirname $0)nerede whichartık mevcut? Aynı değil mi?
UlfR

readlink -fMac OS X 10.11.6'da çalışıyor gibi görünüyor, ancak realpathkutunun dışında çalışıyor.
Grav

9

Benim sistemlerim rozcietrzewiacz tarafından önerildiğirealpath gibi değildir .

Bunu readlinkkomutu kullanarak başarabilirsiniz . Bunu ayrıştırma whichveya başka çözümler üzerinde kullanmanın avantajı , yolun bir kısmı veya yürütülen dosya adı bir bağlantı olsa bile, asıl dosyanın bulunduğu dizini bulabilmenizdir.

MYDIR="$(dirname "$(readlink -f "$0")")"

Metin dosyanız daha sonra şöyle bir değişkende okunabilir:

TEXTFILE="$(<$MYDIR/textfile)"

@ rozcietrzewiacz: Aslında sadece whichönerinize değinmiyordum . Bu normal bir çözüm ya sadece içerir dirnameveya bir kombinasyonunu cdve pwdbir kabuktaki. Readlink burada avantajı vardır. Yine realpathde hemen hemen sadece bir sarıcı gibi görünüyor readlink -f.
Caleb

Nasıl realpathfarklı olduğunu bilmiyorum readlink -f. Sadece bana aynı sonuçları verdiğini görebiliyorum (aksine which).
rozcietrzewiacz

Unutmayın readlink -f(GNU coreutils itibaren) var olma yolun son öğe gerektiren değil, readlink -eyok, ama desteklemediği busybox readlinktaklitleri davranışları, -eonların içinde -fseçenek.
dragon788

8

$0komut dosyasında komut dosyasının tam yolu olacak ve tam yol dirnamealacak ve size yalnızca dizini verecek, böylece cat textfile dosyasına bunu yapabilirsiniz:

$ cat "$(dirname -- "$0")/textfile"

Bu olmadan çalışıyor gibi görünmekle birlikte realpath $0, " $0komut dosyasında komut dosyasının tam yolu olacak " derken yanılıyorsunuz .
rozcietrzewiacz

@ roz ne şekilde?
Michael Mrozek

1
$0örneğin çalıştırılabildiği komuttur ../script.sh.
rozcietrzewiacz

Yani, aslında göreli yolu komut dosyasına, çağrılan komutun bir parçası olarak - mutlak yolu $(dirname "$0")döndürür . Bu, komut dosyalarında çalışırken dizinleri değiştiren sorunlara yol açabilir.
rozcietrzewiacz

@roz Ah, ilginç. Sanırım burada ismine göre bir şey çağırdığı için bir soruna yol açmaz, ama başka şeyleri kırar. Thanks
Michael Mrozek

4

Bunu komut dosyanızın en üstüne koyabilirsiniz:

cd "${BASH_SOURCE%/*}" || exit

BASH_SOURCE iç bash değişkeni aslında bir yol dizisidir. Basit bir dize, örneğin "$ BASH_SOURCE" olarak genişletirseniz, şu anda çalışmakta olan işlevin veya komut dosyasının yol adı olan ilk öğeyi alırsınız.

Kaynak: http://mywiki.wooledge.org/BashFAQ/028


2

Bunları deniyordum ve realpath benim için işe yaramadı. Birlikte gittiğim çözüm:

SCRIPTDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

Şimdiye kadar iyi çalıştı. Yaklaşımla ilgili herhangi bir potansiyel sorun olup olmadığını bilmek istiyorum.


1
Güzel, ama sembolik izleri takip etmez. Bunu dene:SCRIPT_DIR="$( cd "$(dirname "$( readlink -f ${BASH_SOURCE[0]} )")" >/dev/null 2>&1 && pwd)"
OronNavon

1

Kullanırım:

#! /bin/sh -
dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P) || exit
dosomethingwith "${dir%/}/some-file"

Hangi POSIX ve bir dirname sürece çalışmalıdır $0yeni satır karakterleri bitmiyor, değil -ve $CDPATH(ve ayarlanmamış muhtemelen diğer birkaç köşe durumlarda komut baktı-up olmasaydı içinde $PATH).


0

Her zaman whichPATH'tan bir yürütülebilir dosyanın tam yolunu bulmak için kullanırım . Örneğin:

which python

Bunu dirnamekomutla birleştirirseniz, şunları alırsınız:

wp=`which python`
dn=`dirname $wp`
ls $dn
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.