bash - নিজের জন্য সম্পূর্ণ পথ পেতে একটি বাশ স্ক্রিপ্টের জন্য নির্ভরযোগ্য উপায়




path (16)

এই প্রশ্নটি ইতিমধ্যে একটি উত্তর আছে:

আমি একটি সম্পূর্ণ ব্যাস স্ক্রিপ্ট আছে যে তার সম্পূর্ণ পথ জানতে হবে। আমি আপেক্ষিক বা ফ্যান্সি-খুঁজছেন পথগুলি শেষ না করেই এটি করার একটি বিস্তৃত-সামঞ্জস্যপূর্ণ উপায় খুঁজে বের করার চেষ্টা করছি। আমি শুধুমাত্র বাশ সমর্থন করতে হবে, না sh, সিএসএস, ইত্যাদি।

আমি কি এতদূর খুঁজে পেয়েছি:

  1. অ্যাড্রেস থেকে একটি বাশ স্ক্রিপ্টের উত্স ডিরেক্টরি গ্রহণের গ্রহণযোগ্য উত্তর, dirname $0 নামের সাহায্যে স্ক্রিপ্টের পথটি পেয়ে dirname $0 , যা সূক্ষ্ম, তবে এটি একটি আপেক্ষিক পথ (পছন্দ . ) ফেরত পাঠাতে পারে, যা আপনি পরিবর্তন করতে চান স্ক্রিপ্টের ডিরেক্টরি এবং পাথটি এখনও স্ক্রিপ্টের নির্দেশিকায় নির্দেশ করে। তবুও, dirname ধাঁধা অংশ হতে হবে।

  2. OS X (OS X নির্দিষ্ট, কিন্তু উত্তরগুলি নির্বিশেষে নির্বিশেষে কাজ করে) সহ বাশ স্ক্রিপ্টের পরম পথের গ্রহণযোগ্য উত্তরটি এমন একটি ফাংশন দেয় যা $0 আপেক্ষিক দেখায় কিনা তা পরীক্ষা করে এবং এটি যদি PWD- কে প্রাক-মুদ্রণ করে তবে তা পরীক্ষা করে। কিন্তু ফলাফলটি এখনও এটির মধ্যে আপেক্ষিক বিট থাকতে পারে (যদিও সামগ্রিকভাবে এটি সম্পূর্ণ) - উদাহরণস্বরূপ, যদি স্ক্রিপ্ট t ডিরেক্টরি /usr/bin এবং আপনি /usr এবং আপনি bin/../bin/t টাইপ করেন এটি চালানোর জন্য (হ্যাঁ, এটি /usr/bin/../bin হয়), আপনি স্ক্রিপ্টের ডিরেক্টরি পথ হিসাবে /usr/bin/../bin দিয়ে শেষ হয়ে যান। যা কাজ করে , কিন্তু ...

  3. এই readlink সমাধান, যা এই রকম দেখায়:

    # 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`

    কিন্তু readlink নয় এবং দৃশ্যত এটি সমাধানটি জিএনইউ এর readlink উপর নির্ভর করে যেখানে বিএসডি কিছু কারণে কাজ করবে না (আমার চেক করার জন্য একটি বিএসডি-এর মতো সিস্টেম অ্যাক্সেস নেই)।

সুতরাং, এটি করার বিভিন্ন উপায়, কিন্তু তারা সব তাদের caveats আছে।

একটি ভাল উপায় কি হবে? যেখানে "ভাল" মানে:

  • আমাকে পরম পথ দেয়।
  • একটি ধীরে ধীরে (যখন উপরে # 2 উপর মন্তব্য দেখুন) এমনকি সত্ত্বেও ভানুক বিট আউট লাগে। (যেমন, কমপক্ষে মাঝামাঝিভাবে পথটিকে ক্যানোনিক্যালাইজ করে।)
  • * নিক্স সিস্টেমগুলির সবচেয়ে জনপ্রিয় স্বাদগুলিতে (যেমন জিএনইউ / লিনাক্স, বিএসডি ও বিএসডি-মত সিস্টেমগুলি, ওএস এক্স, ইত্যাদি ইত্যাদি) বাশ-ইসম্মে বা প্রায়শই নিশ্চিত হওয়া যায়।
  • যদি সম্ভব হয় তবে বহিরাগত প্রোগ্রামগুলিকে কল করা এড়িয়ে চলুন (উদাহরণস্বরূপ, বাশ বিল্ট ইনস পছন্দ করে)।
  • ( আপডেটেড , হেড আপের জন্য ধন্যবাদ, wich ) এটি সিমলিংকগুলি সমাধান করতে হবে না (আসলে, আমি পছন্দ করি যে এটি তাদের একা ছেড়ে দেওয়া উচিত, কিন্তু এটি কোনও প্রয়োজন নেই)।

একটি শেল স্ক্রিপ্ট পরম পথ পান

এটি পঠনযোগ্য -এফ বিকল্পটি ব্যবহার করে না, এবং তাই এটি BSD / Mac OS X এ কাজ করতে হবে।

সমর্থন

  • উৎস ./script (যখন ডট অপারেটর দ্বারা বলা হয়)
  • পরম পথ / পথ / থেকে / স্ক্রিপ্ট
  • ./Script মত আপেক্ষিক পথ
  • /path/dir1/../dir2/dir3/../script
  • যখন symlink থেকে বলা হয়
  • যখন foo->dir1/dir2/bar bar->./../doe doe->script nested হয় eg) foo->dir1/dir2/bar bar->./../doe doe->script
  • কলার স্ক্রিপ্ট নাম পরিবর্তন যখন

এই কোড কাজ করে না যেখানে আমি কোণার ক্ষেত্রে খুঁজছেন । আমাকে বুঝতে দাও.

কোড

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`]"

পরিচিত ইস্যু

স্ক্রিপ্ট কোথাও ডিস্ক হতে হবে । এটি একটি নেটওয়ার্কের উপর হতে দিন। আপনি যদি এই স্ক্রিপ্টটি একটি পাইপ থেকে চালানোর চেষ্টা করেন তবে এটি কাজ করবে না

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

টেকনিক্যালি বলছে, এটা অনির্ধারিত। বাস্তবিকভাবে বলার অপেক্ষা রাখে না, এই সনাক্ত করার কোন সরল উপায় আছে। (একটি সহ-প্রক্রিয়া পিতামাতার পরিবেশ অ্যাক্সেস করতে পারে না।)


আপনি নিম্নলিখিত পরিবর্তনশীল সংজ্ঞায়িত করার চেষ্টা করতে পারেন:

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

অথবা আপনি বাশে নিম্নলিখিত ফাংশনটি চেষ্টা করতে পারেন:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

এই ফাংশন এক যুক্তি লাগে। যদি ইতিমধ্যে যুক্তিটির একটি সম্পূর্ণ পথ থাকে তবে এটি মুদ্রণ করুন, অন্যথায় $PWD পরিবর্তনশীল + ফাইলের $PWD প্রিন্ট করুন ( ./ prefix ছাড়া)।

সম্পর্কিত:


আমরা যদি ব্যাশ ব্যবহার করি তবে আমি বিশ্বাস করি এটি সবচেয়ে সুবিধাজনক উপায় কারণ এটি কোন বাহ্যিক আদেশগুলিতে কলগুলির প্রয়োজন হয় না:

THIS_PATH="${BASH_SOURCE[0]}";
THIS_DIR=$(dirname $THIS_PATH)

আমার লিনাক্স সিস্টেমে ডিফল্ট প্রতি রিয়েলপথ ইনস্টল করা নেই, আমার জন্য নিম্নলিখিতগুলি কাজ করে:

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

$SCRIPT স্ক্রিপ্টের আসল ফাইল পথ এবং স্ক্রিপ্ট ধারণকারী ডিরেক্টরিটির $SCRIPTPATH

এই ব্যবহার করার আগে এই উত্তর মন্তব্য পড়ুন।


আমি বিস্মিত যে realpath কমান্ড এখানে উল্লেখ করা হয় নি। আমার বোঝা এটা ব্যাপকভাবে পোর্টেবল / ported হয়।

আপনার প্রাথমিক সমাধান হয়ে যায়:

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

এবং আপনার পছন্দের প্রতি সিম্বলিক লিঙ্কগুলি ছেড়ে দেওয়া:

SCRIPT=`realpath -s $0`
SCRIPTPATH=`dirname $SCRIPT`

আমি শুধু এই সমস্যাটি পুনর্বিবেচনা করতে হয়েছিল এবং ভিতর থেকে একটি বাশ স্ক্রিপ্টের উত্স ডিরেক্টরি খুঁজে পেয়েছিলাম। এটি এমন একটি সমাধান যা আমি অতীতে ব্যবহার করেছি তাও বিস্তৃত করে।

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

লিঙ্কযুক্ত উত্তরগুলিতে আরো বৈকল্পিক রয়েছে, উদাহরণস্বরূপ যেখানে স্ক্রিপ্ট নিজেই একটি সিমলিংক।


এই প্রশ্নের উত্তর খুব দেরী, কিন্তু আমি ব্যবহার করি:

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

এক রৈখিক

`dirname $(realpath $0)`

এখানে আমি যা নিয়ে এসেছি তা সম্পাদনা করুন (সম্পাদনা: sfstewman , levigroker , কাইল স্ট্র্যান্ড এবং রব কেনেডি দ্বারা সরবরাহিত কিছু levigroker ), যা বেশিরভাগ আমার "ভাল" মানদণ্ডে মাপসই করা হয় বলে মনে হয়:

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

যে SCRIPTPATH লাইন বিশেষ করে roundabout মনে হয়, কিন্তু স্পেস এবং SCRIPTPATH=`pwd` সঠিকভাবে হ্যান্ডেল করার জন্য আমরা SCRIPTPATH=`pwd` পরিবর্তে এটি প্রয়োজন।

উল্লেখ্য যে গোপনীয় পরিস্থিতি যেমন একটি স্ক্রিপ্ট নির্বাহ করা যা অ্যাক্সেসযোগ্য ফাইল সিস্টেমে কোনও ফাইল থেকে (যা পুরোপুরি সম্ভব) কোনও ফাইল থেকে আসছে না, সেটি এখানে সরবরাহ করা হয় না (অথবা অন্য কোনও উত্তরগুলিতে আমি দেখেছি) )।


এটা চেষ্টা কর:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

গ্রহনযোগ্য সমাধানটির অসুবিধাজনক (আমার জন্য) "উৎস-সক্ষম" হতে পারে না:
যদি আপনি এটি " source ../../yourScript " থেকে কল করেন, $0 হবে " bash "!

নিম্নোক্ত ফাংশন (bash> = 3.0 এর জন্য) আমাকে সঠিক পথ দেয়, তবে স্ক্রিপ্টটিকে সরাসরি বলা যেতে পারে (সরাসরি বা source মাধ্যমে, পরম বা আপেক্ষিক পথ সহ):
("সঠিক পথ" দ্বারা, আমি বলতে চাই স্ক্রিপ্টের সম্পূর্ণ পরম পথ , অন্য পথ থেকে সরাসরি বলা বা সরাসরি " source ")

#!/bin/bash
echo $0 executed

function bashscriptpath() {
  local _sp=$1
  local ascript="$0"
  local asp="$(dirname $0)"
  #echo "b1 asp '$asp', b1 ascript '$ascript'"
  if [[ "$asp" == "." && "$ascript" != "bash" && "$ascript" != "./.bashrc" ]] ; then asp="${BASH_SOURCE[0]%/*}"
  elif [[ "$asp" == "." && "$ascript" == "./.bashrc" ]] ; then asp=$(pwd)
  else
    if [[ "$ascript" == "bash" ]] ; then
      ascript=${BASH_SOURCE[0]}
      asp="$(dirname $ascript)"
    fi  
    #echo "b2 asp '$asp', b2 ascript '$ascript'"
    if [[ "${ascript#/}" != "$ascript" ]]; then asp=$asp ;
    elif [[ "${ascript#../}" != "$ascript" ]]; then
      asp=$(pwd)
      while [[ "${ascript#../}" != "$ascript" ]]; do
        asp=${asp%/*}
        ascript=${ascript#../}
      done
    elif [[ "${ascript#*/}" != "$ascript" ]];  then
      if [[ "$asp" == "." ]] ; then asp=$(pwd) ; else asp="$(pwd)/${asp}"; fi
    fi  
  fi  
  eval $_sp="'$asp'"
}

bashscriptpath H
export H=${H}

কীটি " source " ${BASH_SOURCE[0]} সনাক্ত করা এবং প্রকৃত স্ক্রিপ্টটি ফিরে পেতে ${BASH_SOURCE[0]} করা।


পড়তে সহজ? নীচে একটি বিকল্প। এটা symlinks উপেক্ষা করে

#!/bin/bash
currentDir=$(
  cd $(dirname "$0")
  pwd
)

echo -n "current "
pwd
echo script $currentDir

বাশে একটি সম্পূর্ণ ক্যাননিক্যাল পথ পেতে পাওয়া সবচেয়ে সহজ পদ্ধতি হল cd এবং pwd ব্যবহার করা:

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

$0 পরিবর্তে ${BASH_SOURCE[0]} ব্যবহার করে স্ক্রিপ্টটি <name> বা source <name> হিসাবে আহ্বান করা হয়েছে কিনা তা নির্বিশেষে একই আচরণ সৃষ্টি করে।


ব্যবহার করুন:

SCRIPT_PATH=$(dirname `which $0`)

শেল প্রম্পটে পাস হওয়া যুক্তিটি প্রবেশ করার সময় কার্যকর হওয়া এক্সিকিউটেবলের সম্পূর্ণ পথের প্রিন্ট আউটপুট which মুদ্রণ করে (যা $ 0 এর মধ্যে রয়েছে)

dirname একটি ফাইল নাম থেকে অ ডিরেক্টরি ডিরেক্টরি suffix।

সুতরাং আপনি স্ক্রিপ্টের সম্পূর্ণ পথের সাথে শেষ হয়ে যান, পথটি নির্দিষ্ট করা হয়েছে কিনা তা কোন ব্যাপার না।


সম্ভবত নিম্নলিখিত প্রশ্নের উত্তর গ্রহণ সাহায্য হতে পারে।

আমি কীভাবে GNU এর রিডলিঙ্কের আচরণটি পেতে পারি - একটি Mac এ?

আপনি $ PWD এবং $ 0 abs_dir=${abs_dir//\/.\//\/} ($ 0 এর সাথে শুরু করতে নিখুঁত নয়) অনুমান করে কেবলমাত্র নামটি ক্যানোনিক্যালাইজ করতে চান, কেবল abs_dir=${abs_dir//\/.\//\/} এর লাইন বরাবর abs_dir=${abs_dir//\/.\//\/} প্রতিস্থাপনগুলির একটি সিরিজ ব্যবহার করুন abs_dir=${abs_dir//\/.\//\/} এবং যেমন।

হ্যাঁ, আমি এটা ভয়ঙ্কর দেখছি জানি, কিন্তু এটি কাজ করবে এবং বিশুদ্ধ বাশ।


বোর্ন শেল ( sh ) সঙ্গতিপূর্ণ উপায়:

SCRIPT_HOME=`dirname $0 | while read a; do cd $a && pwd && break; done`




path