স্ক্রিপ্টের মধ্যে থেকে কীভাবে কোনও বাশ স্ক্রিপ্টের উত্স ডিরেক্টরিটি পাবেন


4946

সেই স্ক্রিপ্টের ভিতরে বাশ স্ক্রিপ্টটি যে ডিরেক্টরিটিতে রয়েছে সেটির পথটি কীভাবে পাব ?

আমি অন্য অ্যাপ্লিকেশনটির জন্য একটি ব্যাশ স্ক্রিপ্ট লঞ্চ হিসাবে ব্যবহার করতে চাই। আমি বাশ স্ক্রিপ্টটি যেখানে অবস্থিত সেখানে ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করতে চাই, সুতরাং আমি সেই ডিরেক্টরিতে ফাইলগুলি অপারেটিং করতে পারি:

$ ./application

69
ডিরেক্টরি নামের শেষে যদি কোনও নতুন লাইন থাকে - তবে বর্তমান সমাধানগুলির কোনওটিই কাজ করে না - কমান্ড প্রতিস্থাপনের দ্বারা এগুলি ছিনিয়ে নেওয়া হবে। এটির কাজ করার জন্য আপনি কমান্ড প্রতিস্থাপনের অভ্যন্তরে একটি অ-নিউলাইন অক্ষর যুক্ত করতে পারেন - DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd && echo x)"- এবং কমান্ড প্রতিস্থাপন ছাড়াই এটি সরিয়ে ফেলতে পারেন - DIR="${DIR%x}"
l0b0

80
@ jpmc26 দুটি খুব সাধারণ পরিস্থিতি রয়েছে: দুর্ঘটনা ও নাশকতা। কোনও স্ক্রিপ্ট অপ্রত্যাশিত উপায়ে ব্যর্থ হওয়া উচিত নয় কারণ কেউ, কোথাও, একটি করেছে mkdir $'\n'
l0b0

24
যে কেউ এইভাবে তাদের সিস্টেমকে নাশকতা করতে দেয় সে এই ধরণের সমস্যাগুলি সনাক্ত করার জন্য তা ছেড়ে দেওয়া উচিত নয় ... এমন ধরণের ভুল করতে সক্ষম লোকদের কম ভাড়া দেয়। বাশ ব্যবহারের 25 বছরের মধ্যে আমি কখনই এই জাতীয় জিনিসটি কোথাও ঘটতে দেখেছি না .... এই কারণেই আমাদের কাছে পার্ল এবং দাগ পরীক্ষা করার মতো অভ্যাস রয়েছে (আমি সম্ভবত এটি বলে দোষী হয়ে যাব :)
osirisgothra

3
@ l0b0 বিবেচনা করুন যে আপনার একই সুরক্ষার প্রয়োজন হবে dirnameএবং ডিরেক্টরিটি একটি -(উদাঃ --help) দিয়ে শুরু করা যেতে পারে । DIR=$(reldir=$(dirname -- "$0"; echo x); reldir=${reldir%?x}; cd -- "$reldir" && pwd && echo x); DIR=${DIR%?x}। সম্ভবত এটি ওভারকিল?
স্কোর_উন্ডার

55
আমি দৃ about়ভাবে বিষয় সম্পর্কে এই বাশ এফএকিউ পড়ার পরামর্শ দিই ।
র্যানি আলবেগ ওয়েইন

উত্তর:


6564
#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

এটি একটি দরকারী ওয়ান-লাইনার যা স্ক্রিপ্টের যেখানেই ডাকা হচ্ছে না কেন তার সম্পূর্ণ ডিরেক্টরি নাম দেবে।

এটি ততক্ষণ কাজ করবে যতক্ষণ না স্ক্রিপ্টটি সন্ধান করতে ব্যবহৃত পাথের শেষ উপাদানটি কোনও সিমলিংক নয় (ডিরেক্টরি লিঙ্কগুলি ঠিক আছে)। আপনি যদি স্ক্রিপ্টের কোনও লিঙ্ক নিজেই সমাধান করতে চান তবে আপনার একটি মাল্টি-লাইন সমাধান দরকার:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

এই শেষ alias লেখা, কোনো সমন্বয় সঙ্গে কাজ করবে source, bash -c, symlinks, ইত্যাদি

সাবধান: cdএই স্নিপেট চালানোর আগে আপনি যদি অন্য কোনও ডিরেক্টরিতে যান তবে ফলাফলটি ভুল হতে পারে!

এছাড়াও, $CDPATHগ্যাটাচস এবং স্টার্ডার আউটপুট পার্শ্ব প্রতিক্রিয়াগুলির বিষয়ে নজর রাখুন যদি ব্যবহারকারী তার পরিবর্তে সিডিকে আউটপুট স্টার্ডারে রিডাইরেক্ট করার জন্য সিডি ওভাররাইড করে থাকে (যেমন update_terminal_cwd >&2ম্যাকের দিকে কল করার সময় এস্কেপ সিকোয়েন্স সহ )। >/dev/null 2>&1আপনার cdকমান্ডের শেষে যুক্ত করা উভয় সম্ভাবনার যত্ন নেবে।

এটি কীভাবে কাজ করে তা বোঝার জন্য, আরও ভার্চুজের ফর্মটি চালানোর চেষ্টা করুন:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

এবং এটি এমন কিছু মুদ্রণ করবে:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

27
আপনি যে পদ্ধতিতে source <script>এবং bash <script>: এর সাথে কাজ করে এমন কোনও সমাধানে পৌঁছানোর জন্য ব্যবহারকারী 25866 এর উত্তর দিয়ে এই পদ্ধতির ফিউজ করতে পারেন DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ড্যান মোল্ডিং

21
কখনও কখনও cdস্টাডুটে কিছু প্রিন্ট করে! যেমন, যদি আপনার $CDPATHথাকে .। এই DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )"
কেসটি

182
এই গৃহীত উত্তরটি ঠিক নয়, এটি সিমলিংকের সাথে কাজ করে না এবং অতিরিক্ত জটিল। dirname $(readlink -f $0)সঠিক আদেশ। টেস্টকেসের জন্য gist.github.com/tvlooy/cbfbdb111a4ebad8b93e দেখুন
টিভিলয়

165
@tvlooy IMO আপনার উত্তরটি ঠিক যেমন ঠিক তেমন ঠিক তেমন নয়, কারণ পথে যখন কোনও স্থান থাকে তখন তা ব্যর্থ হয়। একটি নতুন লাইন চরিত্রের বিপরীতে, এটি অসম্ভব বা এমনকি অস্বাভাবিক নয়। dirname "$(readlink -f "$0")"জটিলতা যুক্ত করে না এবং ন্যূনতম পরিমাণে ঝামেলার জন্য উপযুক্ত মাপকাঠি।
অ্যাড্রিয়ান গন্টার

9
@tvlooy আপনার মন্তব্যটি ম্যাকোস (বা সম্ভবত বিএসডি সাধারণভাবে) সামঞ্জস্যপূর্ণ নয়, তবে গৃহীত উত্তরটি রয়েছে। readlink -f $0দেয় readlink: illegal option -- f
আলেকজান্ডার লাজংবার্গ

875

ব্যবহার dirname "$0":

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

pwdআপনি যে ডিরেক্টরিটি এতে অন্তর্ভুক্ত করেছেন সে থেকে স্ক্রিপ্টটি চালাচ্ছেন না বলে একা ব্যবহার করা কার্যকর হবে না।

[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

25
ব্যাশের বাইরেও বহনযোগ্যতার জন্য, $ 0 সর্বদা যথেষ্ট নাও হতে পারে। কমান্ডটি যদি পথে পাওয়া যায় তবে আপনাকে এই কাজটি করতে "টাইপ -p $ 0" বিকল্পের প্রয়োজন হতে পারে।
ড্যারন

10
@ ড্যারন: আপনি কেবল তখনই ব্যবহার করতে পারবেন type -pযদি স্ক্রিপ্টটি কার্যকর হয়। স্ক্রিপ্টটি ব্যবহার করে কার্যকর করা হয় bash test2.shএবং একই নামের সাথে অন্য কোনও স্ক্রিপ্ট এক্সিকিউটেবল হলে অন্য কোনও সূক্ষ্ম ছিদ্রও এটি খুলতে পারে।
ডি.শ্যাওলি

90
@ ড্যারন: তবে যেহেতু প্রশ্নটি ট্যাগ করা হয়েছে bashএবং হ্যাশ-ব্যাং লাইনটি স্পষ্টভাবে উল্লেখ করেছে /bin/bashআমি বলব এটি বাশিজমের উপর নির্ভর করা বেশ নিরাপদ।
জোছিম সউর

34
+1, তবে ব্যবহারের dirname $0ক্ষেত্রে সমস্যাটি হ'ল ডিরেক্টরিটি যদি বর্তমান ডিরেক্টরি হয় তবে আপনি পাবেন .। আপনি স্ক্রিপ্টে ডিরেক্টরিগুলি পরিবর্তন করতে যাচ্ছেন এবং আপনি যে পথটি পেয়েছেন তা ব্যবহার করার প্রত্যাশা না করলে dirname $0এটি ঠিক আছে it সুনির্দিষ্ট পাথ পেতে: pushd `dirname $0` > /dev/null, SCRIPTPATH=`pwd`, popd > /dev/null: pastie.org/1489386 (কিন্তু নিশ্চয় যে পথ প্রসারিত করতে একটি ভাল উপায় কি?)
টি জে Crowder

9
@ টিজে ক্রাউডার আমি নিশ্চিত নই যে dirname $0সমস্যাটি অবশ্যই নিশ্চিত যদি আপনি এটির কোনও ভেরিয়েবলকে অর্পণ করেন এবং তারপরে স্ক্রিপ্টটি চালু করতে এটি ব্যবহার করেন $dir/script.sh; আমি কল্পনা করব এটি এই জাতীয় জিনিসের 90% সময় ব্যবহারের ক্ষেত্রে। ./script.shভাল কাজ করবে।
ম্যাট বি

513

dirnameকমান্ড সবচেয়ে মৌলিক, সহজভাবে দেখা বন্ধ ফাইলের নাম পর্যন্ত পথ পার্স হয় $0(স্ক্রিপ্ট নাম) পরিবর্তনশীল:

dirname "$0"

তবে, যেমন ম্যাট বি দেখিয়েছে, স্ক্রিপ্টটি কীভাবে ডাকা হবে তার উপর নির্ভর করে ফিরে আসা পথটি পৃথক। pwdকাজটি করে না কারণ এটি আপনাকে কেবল বর্তমান ডিরেক্টরিটি কী তা বলে দেয়, স্ক্রিপ্টটি কোন ডিরেক্টরিতে থাকে তা নয় Additionally অতিরিক্তভাবে, যদি কোনও স্ক্রিপ্টের প্রতীকী লিঙ্কটি কার্যকর করা হয়, আপনি একটি (সম্ভবত আপেক্ষিক) পথ পেতে যাচ্ছেন যেখানে লিঙ্কটি থাকে, প্রকৃত স্ক্রিপ্টটি নয়।

অন্য কেউ readlinkকমান্ডটি উল্লেখ করেছেন , তবে এর সহজতম পদ্ধতিতে আপনি ব্যবহার করতে পারেন:

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

readlinkস্ক্রিপ্ট পাথ ফাইল সিস্টেমের মূল থেকে এক নিখুঁত পাথের সমাধান করবে। সুতরাং, একক বা ডাবল ডটস, টিল্ডস এবং / অথবা প্রতীকী লিঙ্কগুলি সহ যে কোনও পাথ একটি সম্পূর্ণ পাথে সমাধান করা হবে।

এইগুলির প্রতিটি প্রদর্শন করে এখানে একটি স্ক্রিপ্ট রয়েছে whatdir.sh:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

আপেক্ষিক পথটি ব্যবহার করে আমার স্কুলে এই স্ক্রিপ্টটি চালাচ্ছেন:

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

আবার, তবে স্ক্রিপ্টের পুরো পথটি ব্যবহার করছে:

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

এখন ডিরেক্টরি পরিবর্তন হচ্ছে:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

এবং অবশেষে স্ক্রিপ্টটি কার্যকর করতে একটি প্রতীকী লিঙ্ক ব্যবহার করে:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat

13
readlinkডিফল্ট ইনস্টলেশনতে কিছু প্ল্যাটফর্মে অবলম্বন করা হবে না। আপনি যদি এটি করতে পারেন তবে এটি এড়াতে চেষ্টা করুন
টিএল

43
হোয়াইটস্পেসের সমস্যাগুলি এড়াতে সবকিছু উদ্ধৃত করতে সাবধান হন:export SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
ক্যাটস্কুল

13
ওএসএক্স ইয়োসেমাইটে 10.10.1 -fতে বিকল্প হিসাবে স্বীকৃত নয় readlinkstat -fপরিবর্তে ব্যবহার করে কাজ করে। ধন্যবাদ
cucu8

11
ওএসএক্সে রয়েছে greadlink, যা মূলত readlinkআমরা সকলেই পরিচিত। এখানে একটি প্ল্যাটফর্মের স্বতন্ত্র সংস্করণ:dir=`greadlink -f ${BASH_SOURCE[0]} || readlink -f ${BASH_SOURCE[0]}`
রবার্ট

6
শুভ কল, @ আরবার্ট এফওয়াইআই, greadlinkসহজে brew install coreutils
হোমব্রিউয়ের

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

সহ সমস্ত সংস্করণে কাজ করে

  • যখন একাধিক গভীরতার নরম লিঙ্কের মাধ্যমে ডাকা হয়,
  • ফাইল যখন এটি
  • যখন স্ক্রিপ্টটি কমান্ড দ্বারা " source" .(ডট) অপারেটর নামে ডাকা হয় ।
  • আর্গ $0কলার থেকে পরিবর্তিত হয় যখন ।
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

বিকল্পভাবে, যদি ব্যাশ স্ক্রিপ্টটি নিজেই একটি আপেক্ষিক সিএমলিংক হয় আপনি এটি অনুসরণ করতে এবং লিঙ্ক-টু স্ক্রিপ্টের পুরো পথটি ফিরে আসতে চান :

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

SCRIPT_PATHএটি যেভাবে বলা হোক না কেন পুরো পথে দেওয়া হয়।
স্ক্রিপ্টের শুরুতে আপনি এটি সনাক্ত করেছেন তা নিশ্চিত করুন।

এই মন্তব্য এবং কোড কোপিলিফ্ট, জিপিএল ২.০ এর অধীনে বা তারপরে সিসি-এসএ 3.0 (ক্রিয়েটিভকমন্স শেয়ার অ্যালাইক) বা তার পরে বাছাইযোগ্য লাইসেন্স। (গ) ২০০৮. সমস্ত অধিকার সংরক্ষিত। কোনও ধরণের ওয়ারেন্টি নেই। তোমাকে সতর্ক করা হল.
http://www.gnu.org/license/gpl-2.0.txt
http://creativecommons.org/license/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656


4
নিস! "পুশ্ড [...] পপড / ডিভ / নাল" এর পরিবর্তে এসিপিএলT_PATH = দ্বারা সংক্ষিপ্ততর করা যেতে পারে readlink -f $(dirname "${VIRTUAL_ENV}");
ই-সন্তুষ্ট

5
এবং পুশড ব্যবহার করার পরিবর্তে ...; $ (সিডি dirname "${SCRIPT_PATH}"অ্যান্ড অ্যান্ড পিডব্লিউড) ব্যবহার করা ভাল না ? তবে যাইহোক দুর্দান্ত স্ক্রিপ্ট!
ওভেনস

6
কোনও স্ক্রিপ্টের জন্য cdএটির বর্তমান ডিরেক্টরিটি cdপরে আবার ফিরে আসার আশঙ্কায় বিপজ্জনক: স্ক্রিপ্টটির ডিরেক্টরিটি চালু হওয়ার পরে ডিরেক্টরিটি পরিবর্তিত করার অনুমতি থাকতে পারে না। (একই ধাক্কা / পপডের জন্য যায়)
অ্যাড্রিয়ান

7
readlink -fজিএনইউ-নির্দিষ্ট। বিএসডির readlinkসেই বিকল্প নেই।
কারা ব্রাইটওয়েল

3
সমস্ত অপ্রয়োজনীয় সাবশেলের সাথে কী? ([ ... ])এর চেয়ে কম দক্ষ [ ... ]এবং এখানে পারফরম্যান্স হিট হওয়ার বিনিময়ে দেওয়া বিচ্ছিন্নতার কোনও সুবিধা নেওয়া হয়নি।
চার্লস ডাফি

110

সংক্ষিপ্ত উত্তর:

`dirname $0`

বা ( সর্বাধিক ):

$(dirname "$0")

17
আপনি স্ক্রিপ্ট উত্স করলে এটি কাজ করবে না। "উত্স আমার / স্ক্রিপ্ট.শ"
অরুনপ্রসাদ রাজকুমার

আমি এটি আমার ব্যাশ স্ক্রিপ্টগুলিতে সর্বদা ব্যবহার করি যা স্টাফকে স্বয়ংক্রিয় করে তোলে এবং প্রায়শই একই স্ক্রিনে অন্যান্য স্ক্রিপ্টগুলিকে অনুরোধ করে। আমি এগুলিতে কখনও ব্যবহার করব না sourceএবং cd $(dirname $0)এটি মনে রাখা সহজ।
kqw

16
@ বিভিস্টিজ: ${BASH_SOURCE[0]}পরিবর্তে এটির $0সাথে কাজ করবেsource my/script.sh
টিমোথী জোনস

@ টিমোথি জোনস যা বাশ ব্যতীত অন্য কোনও শেল থেকে সংগ্রহ করা হলে 100% সময় ব্যর্থ হবে। ${BASH_SOURCE[0]}মোটেও সন্তোষজনক নয়। ${BASH_SOURCE:-0}অনেক ভাল।
ম্যাথিউ CAROFF

106

আপনি ব্যবহার করতে পারেন $BASH_SOURCE:

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

নোট করুন যে আপনার ব্যবহার করা দরকার #!/bin/bashএবং #!/bin/shএটি কোনও বাশ এক্সটেনশন নয়।


14
আমি যখন ./foo/script, তখন $(dirname $BASH_SOURCE)হয় ./foo
পর্যন্ত

1
@ অবধি, এই ক্ষেত্রে আমরা realpath./foo/script এর সম্পূর্ণ পাথ পেতে কমান্ডটি ব্যবহার করতে পারি। তাই dirname $(realpath ./foo/script) স্ক্রিপ্টের পথ দেবে।
পুরুষোথামান পুবাই

73

এটি করা উচিত:

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

এটি প্রতীক এবং পথে ফাঁকা স্থানগুলির সাথে কাজ করে।

জন্য মানুষ পৃষ্ঠা দেখুন dirnameএবং readlink

মন্তব্য ট্র্যাক থেকে মনে হচ্ছে ম্যাক ওএসের সাথে কাজ করবে না। কেন তা আমার কোনও ধারণা নেই। কোন পরামর্শ?


6
সম্পূর্ণ সমাধানের পথের পরিবর্তে স্ক্রিপ্টের মতো ./script.shশোয়ের অনুরোধ করে আপনার সমাধান সহ.
ব্রুনো নেগ্রো জিকা

5
ম্যাকওএসে রিডলিংকের জন্য কোনও বিকল্প নেই। statপরিবর্তে ব্যবহার করুন। তবে তবুও, এটি দেখায় .যে আপনি 'এই' দিরে আছেন কিনা।
ডেনিস দ্য মেনেস

2
আপনাকে coreutilsহোমব্রিউ থেকে ইনস্টল greadlinkকরতে হবে এবং -fম্যাকোএসে বিকল্পটি পেতে ব্যবহার করতে হবে কারণ এটি * লিনাক্স নয় কভারের আওতায় বিএসডি।
ড্রাগন 788

আপনার ডান হাতের সমস্ত অংশের চারপাশে ডাবল উক্তি যুক্ত করা উচিত:DIR="$(dirname "$(readlink -f "$0")")"
হেজেলো

60

pwdবর্তমান চলমান ডিরেক্টরিটি dirnameঅনুসন্ধান করতে এবং একটি নির্দিষ্ট ফাইলের ডিরেক্টরি খুঁজতে (যে কমান্ডটি চালানো হয়েছিল তা হল $0, dirname $0আপনাকে বর্তমান স্ক্রিপ্টের ডিরেক্টরিটি দেওয়া উচিত) can

যাইহোক, dirnameফাইলনামের ডিরেক্টরি অংশটি সঠিকভাবে দেয় যা সম্ভবত বর্তমান ওয়ার্কিং ডিরেক্টরিটির সাথে সম্পর্কিত হতে পারে। যদি আপনার স্ক্রিপ্টে কোনও কারণে ডিরেক্টরি পরিবর্তন করতে হয় তবে তার থেকে আউটপুট dirnameঅর্থহীন হয়ে যায়।

আমি নিম্নলিখিত পরামর্শ:

#!/bin/bash

reldir=`dirname $0`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

এইভাবে, আপনি একটি নিখুঁত, তারপরে বরং আপেক্ষিক ডিরেক্টরি পাবেন।

যেহেতু স্ক্রিপ্টটি পৃথক বাশের ক্ষেত্রে চালিত হবে, কাজী ডিরেক্টরিটি পরে পুনরুদ্ধার করার দরকার নেই, তবে আপনি যদি কোনও কারণে আপনার স্ক্রিপ্টে ফিরে যেতে চান তবে আপনি সহজেই pwdআপনার আগে একটি ভেরিয়েবলের মান নির্ধারণ করতে পারেন ভবিষ্যতে ব্যবহারের জন্য ডিরেক্টরি পরিবর্তন করুন।

যদিও ঠিক

cd `dirname $0`

প্রশ্নের সুনির্দিষ্ট দৃশ্যের সমাধান করে, আমি সাধারণত আরও বেশি উপযোগী হওয়ার নিখুঁত পথ পেয়েছি find


9
আপনি এটির মতো এক লাইনে dirname $0
এগুলি

যদি স্ক্রিপ্টটি অন্য স্ক্রিপ্টের উত্স দেয় এবং আপনি পরবর্তীটির নাম জানতে চান তবে এটি কাজ করে না।
পুনরায় পোস্টার

52

আমি স্বীকৃত উত্তরে ওয়ান-লাইনারটি অনুলিপি করতে বারবার এই পৃষ্ঠায় এসে ক্লান্ত হয়ে পড়েছি। এটির সাথে সমস্যাটি বোঝা এবং মনে রাখা সহজ নয়।

এখানে মনে রাখা সহজ স্ক্রিপ্ট:

DIR="$(dirname "${BASH_SOURCE[0]}")"  # get the directory name
DIR="$(realpath "${DIR}")"    # resolve its full path if need be

2
অথবা, আরও DIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
স্পষ্টতই

কেন এটি গৃহীত উত্তর নয়? realpathএকটি লুপ দিয়ে "ম্যানুয়ালি" সমাধান করা থেকে কোন পার্থক্য আছে readlink? এমনকি readlinkম্যান পেজটি বলেছেNote realpath(1) is the preferred command to use for canonicalization functionality.
ব্যবহারকারী 9123

1
এবং উপায় দ্বারা আমরা realpathআগে প্রয়োগ করা উচিত নয় dirname, পরে নয়? যদি স্ক্রিপ্ট ফাইলটি নিজেই একটি সিমিলিংক হয় ... এটি এমন কিছু দেয় DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"। আসলে সাইমন প্রস্তাবিত উত্তর খুব কাছাকাছি।
ব্যবহারকারী 9123

@ ব্যবহারকারী 9123 আমি মনে করি গ্রহণযোগ্যটি সমস্ত জনপ্রিয় শেল / ডিসট্রোর সাথে সামঞ্জস্য করার চেষ্টা করা হয়েছে। আরও বেশি, আপনি যা করার চেষ্টা করছেন তার উপর নির্ভর করে বেশিরভাগ ক্ষেত্রে লোকেরা প্রকৃত উত্সের ডিরেক্টরিটির পরিবর্তে সিমলিংকটি অবস্থিত ডিরেক্টরিটি পেতে চায়।
ওয়াং

37

আমি মনে করি না যে এটি অন্যরা যতটা সহজ করে দিয়েছে তত সহজ। pwdকাজ করে না, কারণ বর্তমান ডিরেক্টরিটি স্ক্রিপ্টের সাথে প্রয়োজনীয় ডিরেক্টরি নয় directory $0সবসময় না হয় তথ্য আছে। একটি স্ক্রিপ্ট আহবান করার জন্য নিম্নলিখিত তিনটি উপায় বিবেচনা করুন:

./script

/usr/bin/script

script

প্রথম এবং তৃতীয় উপায়ে $0সম্পূর্ণ পথের তথ্য নেই। দ্বিতীয় এবং তৃতীয়, pwdকাজ করে না। তৃতীয় উপায়ে ডিরেক্টরিটি পাওয়ার একমাত্র উপায় হ'ল পথটি চালানো এবং সঠিক মিলের সাথে ফাইলটি সন্ধান করা। মূলত কোডটি ওএস কী করে তা আবার করতে হবে।

আপনি যা জিজ্ঞাসা করছেন তার করার একটি উপায় হ'ল /usr/shareডিরেক্টরিতে থাকা ডেটাটিকে হার্ডকোড করা এবং এর সম্পূর্ণ পথ দ্বারা এটি উল্লেখ করা। ডেটা /usr/binডিরেক্টরিতে যাই হোক না কেন, তাই সম্ভবত এটি করা জিনিস।


9
যদি আপনি তাঁর মন্তব্যটিকে অস্বীকার করার ইচ্ছা করেন তবে প্রমাণ করুন যে কোনও স্ক্রিপ্ট এটি কোড উদাহরণ সহ সঞ্চিত যেখানে অ্যাক্সেস করতে পারে।
রিচার্ড ডিউর

34
SCRIPT_DIR=$( cd ${0%/*} && pwd -P )

এটি নির্বাচিত উত্তরের চেয়ে ছোট। এবং ঠিক পাশাপাশি কাজ করতে দেখা যায়। এটি কেবল 1000 টি ভোটের দাবিদার যাতে লোকেরা এটি উপেক্ষা না করে।
প্যাট্রিক

2
পূর্ববর্তী উত্তরগুলির মধ্যে অনেকগুলি বিশদে বিশদ ব্যাখ্যা করে, স্ক্রিপ্টটি কীভাবে আহ্বান করা হয়েছে তার উপর নির্ভর করে $0নাও pwdসঠিক তথ্য থাকার গ্যারান্টি দেওয়া হয় না।
আইএমএসওপি

34
$(dirname "$(readlink -f "$BASH_SOURCE")")

আমি $BASH_SOURCEবেশি পছন্দ করি $0, কারণ এটি পাঠকদের পক্ষেও ভাল নয়। $(dirname -- "$(readlink -f -- "$BASH_SOURCE")")
ব্লবমাস্টার

32

এটি ম্যাক ওএস এক্স 10.6.6 এ বর্তমান ওয়ার্কিং ডিরেক্টরিটি পেয়েছে:

DIR=$(cd "$(dirname "$0")"; pwd)

27

এটি লিনাক্স নির্দিষ্ট, তবে আপনি ব্যবহার করতে পারেন:

SELF=$(readlink /proc/$$/fd/255)

1
এটি বাশ নির্দিষ্ট, কিন্তু সম্ভবত বাশের আচরণ পরিবর্তন হয়েছে? /proc/fd/$$/255টিটিটির দিকে নির্দেশ করে বলে মনে হচ্ছে, কোনও ডিরেক্টরিতে নয়। উদাহরণস্বরূপ, আমার বর্তমান লগইন শেল-এ, ফাইল বর্ণনাকারী 0, 1, 2 এবং 255 সমস্ত উল্লেখ করে /dev/pts/4। যাই হোক না কেন, ব্যাশের ম্যানুয়ালটিতে fd 255 উল্লেখ করা হয়নি, তাই সম্ভবত এই আচরণের উপর নির্ভর করা
কেথ থম্পসন

2
ইন্টারেক্টিভ শেল! = স্ক্রিপ্ট। যাইহোক realpath ${BASH_SOURCE[0]};এটি যেতে সেরা উপায় বলে মনে হয়।
স্টিভ বেকার

23

এখানে একটি পসিক্স অনুগত ওয়ান-লাইনার রয়েছে:

SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`

# test
echo $SCRIPT_PATH

4
নিজে থেকে বা সুডো ব্যবহার করে কোনও স্ক্রিপ্ট চালানোর সময় আমি এতে সফলতা পেয়েছি, তবে উত্স কল করার সময় নয় / / স্ক্রিপ্ট.শ
মাইকেল আর

এবং যখন cdনতুন পথের নাম মুদ্রণের জন্য কনফিগার করা হয় তখন এটি ব্যর্থ হয়।
অ্যারন দিগুল্লা

18

আমি এই সমস্ত চেষ্টা করেছিলাম এবং কেউই কাজ করেনি। একটি খুব কাছাকাছি ছিল কিন্তু একটি ছোট বাগ ছিল যা এটি খারাপভাবে ভেঙেছে; তারা উদ্ধৃতি চিহ্নগুলিতে পথটি মোড়ানো ভুলে গেছে।

এছাড়াও প্রচুর লোকেরা ধরে নিয়েছে যে আপনি কোনও শেল থেকে স্ক্রিপ্টটি চালাচ্ছেন যাতে আপনি নিজের বাড়িতে নতুন স্ক্রিপ্টটি ডিফল্ট খোলার সময় ভুলে যান।

আকারের জন্য এই ডিরেক্টরিটি ব্যবহার করে দেখুন:

/var/No one/Thought/About Spaces Being/In a Directory/Name/And Here's your file.text

আপনি কীভাবে বা কোথায় চালান তা নির্বিশেষে এটি এটি সঠিকভাবে পেয়েছে:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"

সুতরাং এটি আসল উপযোগী করতে এখানে চলমান স্ক্রিপ্টের ডিরেক্টরিতে কীভাবে পরিবর্তন করবেন:

cd "`dirname "$0"`"

4
স্ক্রিপ্ট অন্য স্ক্রিপ্ট থেকে উত্সাহিত করা হয় না যদি কাজ করে না।
পুনরায় পোস্টার

যদি $ 0 এর শেষ অংশটি একটি প্রতীকী লিঙ্ক হয় যা অন্য ডিরেক্টরিতে প্রবেশের নির্দেশ দেয় ( ln -s ../bin64/foo /usr/bin/foo)।
হেজেলো

17

এখানে সহজ, সঠিক উপায়:

actual_path=$(readlink -f "${BASH_SOURCE[0]}")
script_dir=$(dirname "$actual_path")

ব্যাখ্যা:

  • ${BASH_SOURCE[0]}- স্ক্রিপ্টের পুরো পথ। এই মান সঠিক এমনকি যখন স্ক্রিপ্ট sourced হচ্ছে, যেমন হতে হবে source <(echo 'echo $0')কপি করে প্রিন্ট ব্যাশ , সঙ্গে যখন এটি প্রতিস্থাপন ${BASH_SOURCE[0]}স্ক্রিপ্ট সম্পূর্ণ পথ প্রিন্ট করবে। (অবশ্যই, এটি ধরে নিচ্ছে আপনি বাশের উপর নির্ভরতা নিচ্ছেন ঠিক।

  • readlink -f- নির্দিষ্ট পথে যেকোন সিরামলিঙ্কগুলি পুনরাবৃত্তভাবে সমাধান করে। এটি একটি জিএনইউ এক্সটেনশন, এবং বিএসডি সিস্টেমগুলিতে উপলভ্য নয়। যদি আপনি Mac চালাচ্ছেন, তাহলে আপনি গনুহ ইনস্টল করতে Homebrew ব্যবহার করতে পারেন coreutilsএবং সাথে এই স্থানচ্যুত greadlink -f

  • এবং অবশ্যই dirnameপাথের প্যারেন্ট ডিরেক্টরিটি পায়।


1
greadlink -fদুর্ভাগ্যক্রমে source
ম্যাকটিতে

17

এটি করার সবচেয়ে সংক্ষিপ্ত এবং সর্বাধিক মার্জিত উপায় হ'ল:

#!/bin/bash
DIRECTORY=$(cd `dirname $0` && pwd)
echo $DIRECTORY

এটি সমস্ত প্ল্যাটফর্মগুলিতে কাজ করবে এবং সুপার ক্লিন।

আরও বিশদটি " কোন ডিরেক্টরিটি সেই বাশ স্ক্রিপ্টের মধ্যে রয়েছে? " তে পাওয়া যাবে।


দুর্দান্ত ক্লিন সলিউশন, তবে ফাইলটি সিলেক্ট করা থাকলে এটি কাজ করবে না।
রুটার

16

আমি এই জাতীয় কিছু ব্যবহার করব:

# retrieve the full pathname of the called script
scriptPath=$(which $0)

# check whether the path is a link or not
if [ -L $scriptPath ]; then

    # it is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi

এটাই আসল! সহজ সঙ্গে কাজ shকরে! সাধারণ dirname "$0"ভিত্তিক সমাধানে সমস্যা : যদি স্ক্রিপ্টটি থাকে এবং $PATHকোনও পথ ছাড়াই ডাকে, তারা ভুল ফলাফল দেবে give
নোটলিস্ট

@ নোটিনলিস্ট তাই না স্ক্রিপ্ট মাধ্যমে পাওয়া যায়, তাহলে PATH, $0পরম ফাইলের নাম থাকতে হবে। স্ক্রিপ্ট একটি আপেক্ষিক বা পরম একটি ধারণকারী ফাইলের নাম প্রার্থনা করা হয়, তাহলে /, $0যে উপস্থিত থাকবে।
নিল মেহেহে

উত্সযুক্ত স্ক্রিপ্টের জন্য কাজ করবে না।
অমিত নাইডু

16

এটি ই-সন্তুষ্টির সমাধানের জন্য সামান্য সংশোধন এবং 3bcdnlklvc04a তাদের উত্তরে উল্লেখ করেছেন :

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}    

তাদের তালিকাভুক্ত সমস্ত ক্ষেত্রে এটি এখনও কাজ করা উচিত।

কনসোলবক্সকে ধন্যবাদ popdব্যর্থ হওয়ার পরে এটি প্রতিরোধ করবে pushd


এটি কেবলমাত্র একটি সিমলিংকের নাম না দিয়ে "আসল" ডীরনামটি পেতে পুরোপুরি কাজ করে। ধন্যবাদ!
জে টেলর

1
আরও ভালSCRIPT_DIR=''; pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && { SCRIPT_DIR=$PWD; popd > /dev/null; }
কনসোলবক্স

@ কনসোলবক্স, আপনি কিসের বিরুদ্ধে রক্ষার চেষ্টা করছেন? আমি সাধারণত লজিকাল কন্ডিশনগুলি অন্তর্ভুক্ত করার একটি অনুরাগী, তবে আপনি ধাক্কা খাওয়াতে যে নির্দিষ্ট ত্রুটিটি দেখছিলেন তা কী ছিল? আমি খালি SQLT_DIR ফেরার পরিবর্তে সরাসরি হ্যান্ডেল করার উপায় খুঁজে পেয়েছি।
ফুজ্যাক্স

@ ফুওজাক্স প্রাকৃতিক অনুশীলন popdযেখানে pushdব্যর্থ হয় এমন ক্ষেত্রে (এমনকি বিরল হলেও) এড়াতে । এবং যদি pushdব্যর্থ হয় তবে আপনার কীসের মূল্য হওয়া উচিত বলে মনে করেন SCRIPT_DIR? যৌক্তিক বলে মনে হচ্ছে বা কোনও ব্যবহারকারী কী পছন্দ করতে পারে তার উপর নির্ভর করে ক্রিয়াটি পৃথক হতে পারে তবে অবশ্যই popdকরা ভুল।
কনসোলবক্স

pushd popdএগুলি বাদ দিয়ে এবং পরিবর্তে কমান্ড প্রতিস্থাপনে cd+ ব্যবহার করে এই সমস্ত বিপদগুলি এড়ানো যেতে পারে pwdSCRIPT_DIR=$(...)
অমিত নাইডু

16

জিএনইউ কোর্টিল রয়েছে এমন সিস্টেমগুলির জন্য readlink(উদাঃ লিনাক্স):

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

ব্যবহার করার কোনও প্রয়োজন নেই BASH_SOURCEযখন $0স্ক্রিপ্ট ফাইলের নাম ধারণ করে।


2
স্ক্রিপ্টটি উত্সাহিত না হলে বা 'উত্স' যার ক্ষেত্রে এটি এখনও স্ক্রিপ্টটি যা কিছু পেয়েছিল তা হতে পারে, বা যদি কমান্ড লাইন থেকে '-বাশ' (টিটি লগইন) বা 'বাশ' ('বাশ-এল' এর মাধ্যমে আহবান করা হয়) বা '/ বিন / বাশ '(ইন্টারেক্টিভ নন-লগইন শেল হিসাবে আহ্বান করা হয়েছে)
ওসিরিসগোথর

আমি dirnameকল জুড়ে দ্বিতীয় জোড়া উদ্ধৃতি যোগ । ডিরেক্টরি পাথে ফাঁকা স্থান রয়েছে কিনা প্রয়োজন।
ব্যবহারকারী 1338062

14
#!/bin/sh
PRG="$0"

# need this for relative symlinks
while [ -h "$PRG" ] ; do
   PRG=`readlink "$PRG"`
done

scriptdir=`dirname "$PRG"`

আমি এটি বিভিন্ন সিস্টেমে পরীক্ষা করিনি। তবে এই সমাধানটি হ'ল কমপক্ষে উবুন্টুতে এখনই কাজ করুন, আমার জন্য!
নাটাস ড্র

$0উত্সাহিত স্ক্রিপ্টের জন্য কাজ করবে না
অমিত নাইডু

13

$_এর বিকল্প হিসাবে উল্লেখযোগ্য $0। আপনি যদি বাশের কাছ থেকে কোনও স্ক্রিপ্ট চালাচ্ছেন তবে গ্রহণযোগ্য উত্তরটি সংক্ষিপ্ত করা যেতে পারে:

DIR="$( dirname "$_" )"

মনে রাখবেন এটি আপনার স্ক্রিপ্টের প্রথম বিবৃতি হতে হবে।


4
এটি আপনি sourceবা .স্ক্রিপ্ট ভাঙলে । এই পরিস্থিতিতে $_আপনি যে কমান্ডটি চালিয়ে গিয়েছিলেন তার শেষ প্যারামিটারটি থাকবে .$BASH_SOURCEপ্রতিবার কাজ করে।
ক্লেক

11

আমি দেওয়া অনেক উত্তর তুলনা করেছি, এবং আরও কিছু কমপ্যাক্ট সমাধান সঙ্গে এসেছি। এগুলি আপনার পছন্দের সংমিশ্রণে উত্পন্ন সমস্ত উন্মাদ প্রান্তের কেসগুলি পরিচালনা করবে বলে মনে হয়:

  • পরম পাথ বা আপেক্ষিক পাথ
  • ফাইল এবং ডিরেক্টরি নরম লিঙ্ক
  • আবাহন যেমন script, bash script, bash -c script, source script, অথবা. script
  • ডিরেক্টরি এবং / অথবা ফাইলের নামগুলিতে স্পেস, ট্যাব, নিউলাইনস, ইউনিকোড ইত্যাদি
  • হাইফেন দিয়ে ফাইলের নাম শুরু হয়

আপনি যদি লিনাক্স থেকে চালাচ্ছেন তবে মনে হচ্ছে procহ্যান্ডেলটি ব্যবহার করা বর্তমানে চলমান স্ক্রিপ্টের সম্পূর্ণ সমাধান হওয়া উত্সটি সন্ধান করার জন্য সেরা সমাধান (একটি ইন্টারেক্টিভ সেশনে, স্বতন্ত্রের লিঙ্কটি নির্দেশ করে /dev/pts/X):

resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

এটিতে এটিতে অল্প কদর্যতা রয়েছে তবে ফিক্সটি কমপ্যাক্ট এবং সহজেই বোঝা যায়। আমরা কেবল বাশ আদিম ব্যবহার করছি না, তবে আমি এটির সাথে ঠিক আছি কারণ readlinkকার্যটি যথেষ্টভাবে সরল করে তুলেছে। echo Xএকটি যোগ Xপরিবর্তনশীল স্ট্রিং তাই শেষে যে ফাইলের নাম যে কোন চিহ্ন হোয়াইটস্পেস খাওয়া পেতে না, এবং পরামিতি প্রতিকল্পন ${VAR%X}লাইনের শেষে পরিত্রাণ পায় X। কারণ readlinkএর নিজস্ব একটি নতুন লাইন যুক্ত করা হয়েছে (যা সাধারণত আমাদের পূর্ববর্তী কৌতুকের জন্য না হলে কমান্ড প্রতিস্থাপনে সাধারণত খাওয়া হত), আমাদেরও এ থেকে পরিত্রাণ পেতে হবে। এটি $''উদ্ধৃতি স্কিমটি ব্যবহার করে খুব সহজেই সম্পন্ন হয় , যা আমাদের যেমন এস্কেপ সিকোয়েন্সগুলি ব্যবহার করতে দেয়\n নতুন লাইনের প্রতিনিধিত্ব করতে (এটি আপনি কীভাবে সহজে চালিত নামকরণ ডিরেক্টরি এবং ফাইলগুলি তৈরি করতে পারেন) তা উপস্থাপন করতে।

উপরে লিনাক্সে চলমান স্ক্রিপ্টটি সনাক্ত করার জন্য আপনার প্রয়োজনীয়তাগুলি আবশ্যক, তবে যদি আপনার নিজের কাছে procফাইলসিস্টেম না থাকে বা আপনি যদি অন্য কোনও ফাইলের সম্পূর্ণ সমাধান করা পথটি সন্ধান করতে চান তবে সম্ভবত আপনি নীচের কোডটি সহায়ক মনে করুন। এটি উপরের ওয়ান-লাইনার থেকে কেবল সামান্য পরিবর্তন। যদি আপনি অদ্ভুত ডিরেক্টরি / ফাইলের নামগুলি নিয়ে ঘুরে বেড়াচ্ছেন তবে উভয়টির সাথে আউটপুট পরীক্ষা করা lsএবং readlinkতথ্যবহুল, যেমন lsআউটপুটটি "সরলিকৃত" হবে, ?নতুন লাইনের মতো জিনিসের বিকল্প হবে ।

absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}

ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"

আমি /dev/pts/30উবুন্টু 14.10 ডেস্কটপে বাশ পেয়েছি ।
ড্যান ড্যাসক্লেস্কু

@ ড্যানডাসকলেসকু ওয়ান-লাইনার ব্যবহার করছেন? বা নীচে পুরো কোড স্নিপেট? এবং আপনি এটিকে কোনও জটিল পথের নাম খাওয়াচ্ছেন?
বিলিজেএমসি

এক লাইন প্লাস আরেকটি লাইন echo $resolved, আমি যেমন সংরক্ষিত d, chmod +x d, ./d
ড্যান ড্যাসক্লেস্কু

@ ড্যানডাসকলেসকু আপনার স্ক্রিপ্টের প্রথম লাইনটি হওয়া দরকার#!/bin/bash
বিলিজেমসি

10

ব্যবহার করার চেষ্টা করুন:

real=$(realpath $(dirname $0))

1
আমি শুধু জানতে চাই, কেন এই পথটি ভাল নয়? এটি আমার পক্ষে খারাপ এবং সঠিক বলে মনে হয়নি। কেউ কেন এটি নিম্নোক্ত বলে ব্যাখ্যা করতে পারে?
শো ইয়া

7
রিয়েলপথ কোনও স্ট্যান্ডার্ড ইউটিলিটি নয়।
স্টিভ বেনেট

2
লিনাক্সে, রিয়েলপথটি একটি স্ট্যান্ডার্ড ইউটিলিটি (জিএনইউ কোর্টিলস প্যাকেজের অংশ), তবে এটি কোনও অন্তর্নির্মিত ব্যাশ নয় (অর্থাত্ ব্যাশ নিজেই সরবরাহিত একটি ফাংশন)। আপনি যদি লিনাক্স চালাচ্ছেন তবে এই পদ্ধতিটি সম্ভবত কাজ করবে, যদিও আমি বিকল্পটি $0ব্যবহার করতাম ${BASH_SOURCE[0]}যাতে এই পদ্ধতিটি কোনও ফাংশন সহ যে কোনও জায়গায় কাজ করতে পারে।
ডগ রিচার্ডসন

3
এই উত্তরের ক্রিয়াকলাপটি ভুল। আপনাকে প্রথমে সিমলিংকটি সমাধান করতে হবে, তারপরে করুন dirnameকারণ শেষ অংশটি $0এমন একটি সিমলিংক হতে পারে যা কোনও ফাইলকে নির্দেশ করে যা সিমলিংকের মতো একই ডিরেক্টরিতে নেই। এই উত্তরে বর্ণিত সমাধানটি কেবলমাত্র ডিরেক্টরিটির ডিরেক্টরি নয়, যেখানে এটি সিমেলিংক সংরক্ষণ করে সেই ডিরেক্টরিটির পথ পায়। তদ্ব্যতীত, এই সমাধানটি উদ্ধৃতি অনুপস্থিত। যদি पथটিতে বিশেষ অক্ষর থাকে তবে এটি কাজ করবে না।
হিগেলো

3
dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
কোস্টিয়ান্টিন পোনোমারেঙ্কো

9

নিম্নলিখিত ক্রস সামঞ্জস্যপূর্ণ সমাধান চেষ্টা করুন:

CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"

যেমন কমান্ডগুলি যেমন উপলব্ধ realpathবা readlinkনাও পারা যায় (অপারেটিং সিস্টেমের উপর নির্ভর করে)।

দ্রষ্টব্য: বাশে, ${BASH_SOURCE[0]}পরিবর্তে এটি ব্যবহার করার পরামর্শ দেওয়া হয়েছে $0, অন্যথায় ফাইলটি ( source/ .) উত্সাহিত করার সময় পাথটি ভেঙে যেতে পারে ।

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

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

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

সম্পর্কিত:


রিয়েলপথ ফাংশন সম্পর্কে আরও ব্যাখ্যা করুন।
ক্রিস

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

স্ক্রিপ্ট সিলেক্ট করা অবস্থায় আপনার ক্রস-সামঞ্জস্যপূর্ণ সমাধান কাজ করে না।
জাকুব জিরুতকা

9

আমি বিশ্বাস করি আমি এটি পেয়েছি। আমি পার্টিতে দেরি করেছি, তবে আমি মনে করি কেউ কেউ এই থ্রেডটি সামনে এলে এখানে উপস্থিত থাকার প্রশংসা করবে। মন্তব্যগুলি ব্যাখ্যা করা উচিত:

#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.

## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.

## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).

## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.

## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.

## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.

## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)

## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.

## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.

##===-------------------------------------------------------------------===##

for argv; do :; done # Last parameter on command line, for options parsing.

## Error messages. Use functions so that we can sub in when the error occurs.

recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.

# Probably best not to install as 'pathfull', if you can avoid it.

pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"

## 'test and 'ls' report different status for bad symlinks, so we use this.

 if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null;  then
    errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then
    recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
    dangling 1>&2; exit 1; fi
 fi

## Not a link, but there might be one in the path, so 'cd' and 'pwd'.

 if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
   printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
 fi

## Walk the symlinks back to the origin. Calls itself recursivly as needed.

 while [ "$link" ]; do
   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
   case "$newlink" in
    "$link") dangling 1>&2 && exit 1                                       ;;
         '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
          *) link="$newlink" && pathfull "$link"                           ;;
   esac
 done
 printf "$(pwd)/$(basename "$newlink")\n"
}

## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".

if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"

# Yay ANSI l33t codes! Fancy.
 printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
 printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
 printf " From within an invocation of a script, locate the script's "
 printf "own file\n         (no matter where it has been linked or "
 printf "from where it is being called).\n\n"

else pathfull "$@"
fi

8

স্ক্রিপ্ট তথ্য পাওয়ার জন্য এগুলি সংক্ষিপ্ত উপায়:

ফোল্ডার এবং ফাইল:

    Script: "/tmp/src dir/test.sh"
    Calling folder: "/tmp/src dir/other"

এই আদেশগুলি ব্যবহার করে:

    echo Script-Dir : `dirname "$(realpath $0)"`
    echo Script-Dir : $( cd ${0%/*} && pwd -P )
    echo Script-Dir : $(dirname "$(readlink -f "$0")")
    echo
    echo Script-Name : `basename "$(realpath $0)"`
    echo Script-Name : `basename $0`
    echo
    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
    echo Script-Dir-Relative : `dirname $0`
    echo
    echo Calling-Dir : `pwd`

এবং আমি এই আউটপুট পেয়েছি:

     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir

     Script-Name : test.sh
     Script-Name : test.sh

     Script-Dir-Relative : ..
     Script-Dir-Relative : ..

     Calling-Dir : /tmp/src dir/other

আরও দেখুন: https://pastebin.com/J8KjxrPF



আমি মনে করি আমার উত্তরটি ঠিক আছে কারণ একটি সহজ ওয়ার্কিং সংস্করণ খুঁজে পাওয়া শক্ত। এখানে আপনার পছন্দসই কোড যেমন সিডি + পিডাব্লুডি, ডাইরনাম + রিয়েলপথ বা ডেরনাম + রিডলিঙ্ক নিতে পারেন। আমি নিশ্চিত নই যে সমস্ত অংশগুলি এর আগে উপস্থিত ছিল এবং বেশিরভাগ উত্তর জটিল এবং অতিরিক্ত লোড। আপনি যে কোডটি ব্যবহার করতে চান তা এখানে পাইক করতে পারেন। ভবিষ্যতে আমার যেমন প্রয়োজন তেমন দয়া করে এটি অপসারণ করবেন না: ডি
ইউজার 8461

8

এটি ব্যাশ -৩.২ এ কাজ করে:

path="$( dirname "$( which "$0" )" )"

আপনি যদি একটি থাকে তাহলে ~/binআপনার ডিরেক্টরির $PATH, আপনি Aএই ডিরেক্টরির ভিতরে। এটি স্ক্রিপ্ট উত্স~/bin/lib/B । আপনি জানেন যে অন্তর্ভুক্ত স্ক্রিপ্টটি মূল libডিরেক্টরিটির সাথে সম্পর্কিত, উপ - ডিরেক্টরিতে, তবে এটি যেখানে ব্যবহারকারীর বর্তমান ডিরেক্টরি সম্পর্কিত নয় relative

এটি নিম্নলিখিত দ্বারা অভ্যন্তরীণভাবে সমাধান করা হবে A ) :

source "$( dirname "$( which "$0" )" )/lib/B"

ব্যবহারকারী কোথায় আছেন বা কীভাবে তিনি স্ক্রিপ্টটি কল করেন তা বিবেচনাধীন নয়, এটি সর্বদা কাজ করবে।


3
বিষয়টি whichখুব বিতর্কিত। type, hashএবং অন্যান্য বিল্টিনগুলি একই জিনিসকে ব্যাশে আরও ভাল করে। whichদয়ালু আরও পোর্টেবল, যদিও এটি whichটিসিএস-এর মতো অন্যান্য শেলগুলিতে সত্যই ব্যবহৃত হয় না , এটি বিল্টিন হিসাবে রয়েছে।
মনিকা পুনরায় ইনস্টল করুন

"সর্বদা"? একদমই না. whichবাহ্যিক সরঞ্জাম হওয়ায় এটি বিশ্বাস করার কোনও কারণ নেই যে এটি প্যারেন্ট শেলের সাথে একইরকম আচরণ করে।
চার্লস ডাফি

7

আমার দৃষ্টিতে সেরা কমপ্যাক্ট সমাধানটি হ'ল:

"$( cd "$( echo "${BASH_SOURCE[0]%/*}" )"; pwd )"

বাশ ছাড়া আর কোনও কিছুর উপর নির্ভরতা নেই। ব্যবহারের dirname, readlinkএবং basenameঅবশেষে সামঞ্জস্যজড়িত কোনো সমস্যা হতে হবে যাতে তারা ভাল সব সম্ভব এ যদি এড়িয়ে যাওয়া হয়।


2
আপনি সম্ভবত যে স্ল্যাশ যোগ করা উচিত: "$( cd "$( echo "${BASH_SOURCE[0]%/*}/" )"; pwd )"। আপনি যদি না করেন তবে আপনার রুট ডিরেক্টরিতে সমস্যা হবে। এছাড়াও আপনি এমনকি প্রতিধ্বনি ব্যবহার করতে হবে কেন?
কনসোলবক্স 17

dirnameএবং basenameপসিক্স মানসম্মত হয়, তবে কেন সেগুলি ব্যবহার করা এড়াবেন? লিঙ্ক: dirname,basename
myrdd

দুটি অতিরিক্ত প্রক্রিয়া কাঁটাচামচ প্রতিরোধ এবং শেল বিল্ট-ইনগুলিতে সংযুক্ত থাকা একটি কারণ হতে পারে।
অমিত নাইডু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.