Başlanğıc script üçün etibarlı bir yol özünüz üçün tam yol almaq üçün?

Onun tam yolunu bilmək üçün lazım olan bir bash script var. Mən nisbi və ya qorxulu yollarla bitmədən bunu etmək üçün geniş şəkildə uyğun bir yol tapmağa çalışıram. Mən bash deyil, sh, csh və s.

Bu günə qədər gördüyüm şeylər:

  • Batch skriptinin qaynaq kataloquunu dirname $0 yolu ilə aldığı ünvanı içərisindən alır, bu, normaldır, lakin nisbi bir yola dönə bilər (məsələn . ), dirname $0 dəyişmək və dizinin yolunu göstərmək istəsəniz, hansı bir problemdir? script Lakin, dirname bulmacanın bir hissəsi olacaq.

  • " Bash scriptinin OSX ilə mütləq bir yoludur " (OS X-yə xüsusi, lakin cavab müstəqil şəkildə işləyir) $0 nisbətən görünür və yoxsa $PWD -ə köçürüləcəyini yoxlayacaq bir funksiya verir. Lakin nəticənin nisbi bitləri olsa da (ümumiyyətlə, bu, mütləq olsa da) - məsələn, /usr/bin skript varsa və /usr və siz bin/../bin/t bəli, bu qarışıqdır), script qovluğunun yolunu /usr/bin/../bin əldə /usr/bin/../bin . Hansı biri işləyir , amma ...

  • Bu readlink həlli bu kimi görünür:

     # Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) # Absolute path this script is in. /home/user/bin SCRIPTPATH=`dirname $SCRIPT` 

    Amma readlink POSIX deyil və yəqin ki, həlli BSD-nin nədənsə işləməyəcəyi GNU readlink istinad edir (mən yoxlama üçün BSD kimi sistemə daxil deyiləm).

Beləliklə, bunu etmək üçün müxtəlif yollar var, amma onların hamısı birbaşa sifarişlərdir.

Nə yaxşı olardı? "Daha yaxşı" deməkdir:

  • Mənə mütləq yol verir.
  • Mürəkkəb bir şəkildə çağırıldığında belə funky bitləri atır (yuxarıda 2 saylı şərhə bax). (Məsələn, ən az orta dərəcədə kanonik yol.)
  • Yalnız bash -izm və ya nix-sistemlərin (GNU / Linux, BSD və BSD kimi sistemlər, OS X və s.) Ən populyar aksessuarlarında olacaq şeylərə əsaslanır.
  • Mümkün olduğu təqdirdə xarici proqramları çağırmaqdan çəkinin (məsələn, bash üstünlükləri gömülü modullara üstünlük verir).
  • ( Yenilənib , rəhbərliklər üçün təşəkkür edirik) Sembolik əlaqələri həll etmək üçün ehtiyac yoxdur (əslində mən onları tək buraxmağı üstün edirəm, amma bu bir tələb deyil).
428
23 янв. TJ Crowder 23 yanvarda təyin olundu 2011-01-23 16:24 '11 'də 16:24' də 2011-01-23 16:24 'də
@ 23 cavab

Əsasən mənim "ən yaxşı" meyarlara uyğun olaraq görünür olan (mənim redaktə: plus sfstewman , levigroker , Kyle StrandRob Kennedy tərəfindən verilmiş bəzi tövsiyələr):

 SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" 

Bu xətt SCRIPTPATH xüsusilə sirkulyar görünür, ancaq boşluqlar və simvolik əlaqələri düzgün idarə etmək üçün SCRIPTPATH=`pwd` , ona lazımdır.

Erişici bir fayl sistemində heç bir fayldan gəlməyəcəyi (tamamilə mümkündür) bir skriptin yerinə yetirilməsi kimi ezoterik vəziyyətlər də orada (və ya görmüş olduğum digər cavablarda) xidmət edilmir.

306
23 янв. Cavab TJ Crowder tərəfindən 23 Yanvar verildi 2011-01-23 16:25 '11 'də 16:25' də 2011-01-23 16:25

realpath əmrinin burada göstərilməməsi təəccübləndim. Anlayıram ki, bu, geniş yayılmışdır.

İlkin qərarınız:

 SCRIPT=`realpath $0` SCRIPTPATH=`dirname $SCRIPT` 
border=0

Və simvolik əlaqələri seçimlərinizə uyğun olaraq həll edilməməlidir:

 SCRIPT=`realpath -s $0` SCRIPTPATH=`dirname $SCRIPT` 
128
20 июня '12 в 10:11 2012-06-20 10:11 Cavab Darshan Rivka Whittle tərəfindən verilir 20 İyun 2012 at 10:11 2012-06-20 10:11

Bash'taki tam kanonik yolu tapdığım en asan yol cd ve pwd kullanmaktır:

 ABSOLUTE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")"  pwd)/$(basename "${BASH_SOURCE[0]}")" 

$0 əvəzinə ${BASH_SOURCE[0]} istifadə edərək, skriptə <name> və ya source <name>

118
02 февр. Cavab Andrew Norrie tərəfindən verilir 02 fevral. 2012-02-02 07:03 '12 at 7:03 2012-02-02 07:03

Mən bu gün bu məsələni nəzərdən keçirmək və on123.ru.ite/questions/122 / .... Keçmişdə istifadə etdiyim həlli təsvir edir.

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

Məsələn əlaqədar cavab ilə daha çox variant var. ssenarinin özü simvolik bir link olduğu halda.

32
15 июня '13 в 15:21 2013-06-15 15:21 cavab 15 iyun 2013-cü il saat 15:21 'də Felix Rabe tərəfindən verilir

Shell skriptinin mütləq yolunu alın

Read-linkdə -f variantını istifadə etmir, bsd / mac-osx-də işləməlidir

Dəstək

  • source./ script (Nöqtə operatoru tərəfindən çağırıldığında . )
  • Mütləq yol / yol / in / skript
  • Nisbi bir şəkildə, kimi. / skript
  • /path/dir1/../dir2/dir3/../script
  • Sembolik bir linkdən çağırıldığında
  • Sembolik bir link foo->dir1/dir2/bar bar->./../doe doe->script , məsələn) foo->dir1/dir2/bar bar->./../doe doe->script
  • Zəng edənin scriptin adını dəyişdirdiyi zaman

Bu kodun işləmədiyi bucaqlı vəziyyətləri axtarıram . Xahiş edirik mənə bildirin.

kodu

 pushd . > /dev/null SCRIPT_PATH="${BASH_SOURCE[0]}"; while([ -h "${SCRIPT_PATH}" ]); do cd "`dirname "${SCRIPT_PATH}"`" SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")"; done cd "`dirname "${SCRIPT_PATH}"`" > /dev/null SCRIPT_PATH="`pwd`"; popd > /dev/null echo "srcipt=[${SCRIPT_PATH}]" echo "pwd =[`pwd`]" 

Famous issuse

Skript hər yerdə diskdə olmalıdır, şəbəkədə olsun. Bu skripti PIPE-dən çalıştırmaya çalışarsanız, bu işləməyəcəkdir.

 wget -o /dev/null -O - http://host.domain/dir/script.sh |bash 

Texniki cəhətdən bu, müəyyən edilməmişdir.
Praktiki olaraq, bunu aşkarlamaq üçün ağlabatan bir yol yoxdur. (sovet dövründə ana ünsiyyətə girə bilmədi)

28
30 авг. Cavab GreenFox 30 aug tərəfindən verilir . 2012-08-30 16:04 '12 at 4:04 pm 2012-08-30 16:04

Istifadə haqqında:

 SCRIPT_PATH=$(dirname `which $0`) 

which dəlilin qabığın istifadəsinə daxil edildikdə yerinə yetiriləcək yürütüle bilən faylın tam yolunu yazan ($ 0 olan)

dirname fayl adı ilə directory-free suffixes ayırır

Buna görə, sonda, yolun müəyyən olub-olmamasının asılı olmasına baxmayaraq, ssenarinin tam yolunu alırsınız.

22
09 сент. Cavab Matt 09 Sentyabr. 2013-09-09 22:01 '13 saat 10:01 'da 2013-09-09 22:01

Realpath mənim Linux sistemimdə default olaraq quraşdırılmadığından aşağıdakılar mənim üçün işləyir:

 SCRIPT="$(readlink --canonicalize-existing "$0")" SCRIPTPATH="$(dirname "$SCRIPT")" 

$SCRIPT $SCRIPTPATH real yolun yolunu və $SCRIPTPATH ehtiva edən kataloqun real yolunu ehtiva edir.

Bunu istifadə etməzdən əvvəl bu cavabı şərh edin.

19
09 мая '13 в 20:06 2013-05-09 20:06 Cavab ypid verilir 09 May '13 at 20:06 2013-05-09 20:06

Bu suala cavab çox gec, ancaq mən istifadə edirəm:

 SCRIPT=$( readlink -m $( type -p $0 )) # Full path to script BASE_DIR=`dirname ${SCRIPT}` # Directory script is run in NAME=`basename ${SCRIPT}` # Actual name of script even if linked 
9
24 марта '14 в 19:11 2014-03-24 19:11 Cavab verilir Stormcloud 24 mart '14 19:11 2014-03-24 19:11

Pulsuz və pulsuz icma istifadə üçün öz realpath-lib məhsulunu GitHub -da yerləşdirdik.

A utancsız plugin, lakin bu bash kitabxanası ilə:

 get_realpath <absolute|relative|symlink|local file> 

Bu funksiya kitabxananın əsasını təşkil edir:

 function get_realpath() { if [[ -f "$1" ]] then # file *must* exist if cd "$(echo "${1%}" return 0 # success } 

Heç bir kənar asılılıq tələb etmir, yalnız Bash 4+. get_dirname , get_filename , get_stemname və funksiyaları da var validate_path validate_realpath . Pulsuz, təmiz, sadə və yaxşı sənədləşdirilmişdir, buna görə də təhsil məqsədləri üçün istifadə edilə bilər və şübhəsiz ki, bu təkmilləşdirilə bilər. Müxtəlif platformalarda keçir.

Yeniləmə. Bəzi revizyon və testlərdən sonra, yuxarıda göstərilən funksiyanı eyni nəticə əldə edən (dirname, yalnız saf Bash istifadə etməyən), lakin daha çox məhsuldarlıqla əvəz etdik:

 function get_realpath() { [[ ! -f "$1" ]]  return 1 # failure : file does not exist. [[ -n "$no_symlinks" ]]  local pwdp='pwd -P' || local pwdp='pwd' # do symlinks. echo "$( cd "$( echo "${1%}" # echo result. return 0 # success } 

Bu da fiziki sistemə simvolik əlaqələri aradan qaldırmağa imkan verən no_symlinks mühitinin yaradılması daxildir. Varsayılmadı olaraq, dəyişməz simvolik əlaqələri saxlayır.

5
02 окт. cavab AsymLabs 02 oct tərəfindən verilir . 2013-10-02 19:28 '13 at 19:28 2013-10-02 19:28

sh uyğun yol:

 SCRIPT_HOME=`dirname $0 | while read a; do cd $a  pwd  break; done` 
4
11 нояб. Cavab Haruo Kinoshita 11-də verilir . 2016-11-11 21:48 '16 at 21:48 2016-11-11 21:48

Aşağıdakı dəyişənləri müəyyən etməyə çalışa bilərsiniz:

 CWD="$(cd -P -- "$(dirname -- "$0")"  pwd -P)" 

ya da bash-də aşağıdakı funksiyanı cəhd edə bilərsiniz:

 realpath () { [[ $1 = }" != "$ascript" ]]; then if [[ "$asp" == "." ]] ; then asp=$(pwd) ; else asp="$(pwd)/${asp}"; fi fi fi eval $_sp="'$asp'" } bashscriptpath H export H=${H} 

Açar " source " vəziyyətini aşkar etməlidir və faktiki scripti qaytarmaq üçün ${BASH_SOURCE[0]} istifadə edin.

1
24 июня '11 в 4:43 2011-06-24 04:43 Cavab VonC tərəfindən 24 iyun 'da 4:43' də verildi 2011-06-24 04:43

Oxumaq asan? alternativ. Simvolik əlaqələri görməyin.

 #!/bin/bash currentDir=$( cd $(dirname "$0") pwd ) echo -n "current " pwd echo script $currentDir 
1
12 мая '16 в 21:43 2016-05-12 21:43 cavab 12 may 16: 00-da 21:43 2016-05-12 21:43 tarixində gerardw tərəfindən verilir

Aşağıdakı yanaşmanı bir müddət uğurla istifadə etdim (OSX-də deyil) və mən gördüyüm qədər yalnız daxili kabuğu istifadə edir və "mənbə foobar.sh" işini idarə edir.

Aşağıdakı nümunə kodundan olan problemlərdən biri (həsrətlə birlikdə) funksiyadan bir funksiya çağırışı zamanı düzgün və ya düzgün olmaya bilən $ PWD istifadə edir. Beləliklə, işlənilməlidir.

 #!/bin/bash function canonical_path() { # Handle realtive vs absolute path [ ${1:0:1} == '/' ]  x=$1 || x=$PWD/$1 # Change to dirname of x cd ${x%} cd $OLDPWD } echo $(canonical_path "${BASH_SOURCE[0]}") type [ type cd type echo type pwd 
0
19 апр. cavab verildi andro 19 Apr 2014-04-19 00:38 '14 'də 0:38 2014-04-19 00:38' da

Bunun bir başqa yolu:

 shopt -s extglob selfpath=$0 selfdir=${selfpath%%+([!/])} while [[ -L "$selfpath" ]];do selfpath=$(readlink "$selfpath") if [[ ! "$selfpath" =~ ^/ ]];then selfpath=${selfdir}${selfpath} fi selfdir=${selfpath%%+([!/])} done echo $selfpath $selfdir 
0
19 дек. Meow cavab 19 Dek 2014-12-19 17:02 '14 at 17:02 2014-12-19 17:02

Sadəcə, lənətləmək, mən birbaşa bir mətnə ​​əsaslanan mətnə ​​əsaslanan bir ssenariyə bir az hackladım. İnşallah bütün həddindən artıq həssas hadisələri yaxaladıq. Başqa bir cavabda qeyd etdiyim ${var//pat/repl} işləməyəcək, çünki onu, məsələn, /foo/../ əvəz etmək üçün problem olan ən qısa matçını dəyişdirməyə məcbur edə bilməzsiniz. /*/../ hər şeyin qarşısında yalnız bir rekord deyil. Və bu nümunələr həqiqətən normal ifadələr olmadığından, bu iş üçün necə edilə biləcəyini görmürəm. Beləliklə, burada mənimlə zövq alan gözəl bir qarışıq qərardır .;)

Yeri gəlmişkən, qabığın hər hansı xammal hallarını tapmaqla mənə bildirin.

 #!/bin/bash canonicalize_path() { local path="$1" OIFS="$IFS" IFS=$'/' read -a parts < <(echo "$path") IFS="$OIFS" local i=${#parts[@]} local j=0 local back=0 local -a rev_canon while (($i > 0)); do ((i--)) case "${parts[$i]}" in ""|.) ;; ..) ((back++));; *) if (($back > 0)); then ((back--)) else rev_canon[j]="${parts[$i]}" ((j++)) fi;; esac done while (($j > 0)); do ((j--)) echo -n "/${rev_canon[$j]}" done echo } canonicalize_path "/.././..////../foo/./bar//foo/bar/.././bar/../foo/bar/./../..//../foo///bar/" 
0
23 янв. cavab 23 yanvar verilir . 2011-01-23 17:53 '11 at 17:53 2011-01-23 17:53

Tək layneri

 `dirname $(realpath $0)` 
-2
18 дек. Abhijit tərəfindən verilmiş cavab 18 dekabr 2015-12-18 05:02 '15 at 5:02 2015-12-18 05:02

Sadəcə, bu mənim üçün işləyən şeydir:

 MY_DIR=`dirname $0` source $MY_DIR/_inc_db.sh 
-3
15 нояб. Cavab Elendurwen tərəfindən verilir . 2016-11-15 14:31 '16 'da 2:31 ' da 2016-11-15 14:31

etiketləri ilə bağlı digər suallar və ya sual verin