ডিরেক্টরিটি ইতিমধ্যে সেখানে না থাকলে $ PATH এ যুক্ত করুন


126

ডিরেক্টরিটি ইতিমধ্যে সেখানে না থাকলে কেবল $ PATH- তে ডিরেক্টরি যুক্ত করার জন্য কি কেউ বাশ ফাংশন লিখেছেন?

আমি সাধারণত PATH এ জাতীয় কিছু ব্যবহার করে যুক্ত করি:

export PATH=/usr/local/mysql/bin:$PATH

যদি আমি .Bash_ প্রোফাইলে আমার PATH বানাই, তবে আমি যে অধিবেলে থাকি তা লগইন সেশন না হওয়া পর্যন্ত এটি পড়া হয় না - যা সর্বদা সত্য নয়। যদি আমি .Bashrc এ আমার প্যাথটি নির্মাণ করি, তবে এটি প্রতিটি সাবশেলের সাথে চলে। সুতরাং আমি যদি একটি টার্মিনাল উইন্ডো চালু করি এবং তারপরে পর্দা চালাব এবং তারপরে একটি শেল স্ক্রিপ্ট চালাব, আমি পেয়েছি:

$ echo $PATH
/usr/local/mysql/bin:/usr/local/mysql/bin:/usr/local/mysql/bin:....

আমি ডাকা বাশ ফাংশন তৈরির চেষ্টা করতে যাচ্ছি add_to_path()যেখানে এটি ডিরেক্টরি না থাকলে কেবল ডিরেক্টরি যুক্ত করে। তবে, যদি ইতিমধ্যে কেউ এ জাতীয় কিছু লিখেছেন (বা খুঁজে পেয়েছেন) তবে আমি এটিতে সময় ব্যয় করব না।


সহায়তা করতে পারে এমন কিছু পরিকাঠামোর জন্য stackoverflow.com/questions/273909/… দেখুন ।
dmckee


যদি আপনি সমস্যাটিকে "ইতিমধ্যে সেখানে না থাকলে কেবল যোগ করার" হিসাবে ফ্রেম করেন তবে you'reোকানো আইটেমটি শুরুতে হওয়া গুরুত্বপূর্ণ হওয়া সত্ত্বেও আপনি অভদ্রভাবে আশ্চর্য হয়ে যাবেন কিন্তু এটি সেখানে বাধা দেয় না। উপাদানটি সন্নিবেশ করা, এবং তারপরে অনুলিপিগুলি সরিয়ে ফেলার জন্য আরও ভাল পন্থা হ'ল তাই নতুন প্রবেশিকাটি যদি ইতিমধ্যে সেখানে উপস্থিত থাকে তবে কার্যকরভাবে এটি শুরুতে স্থানান্তরিত হবে।
ডন হ্যাচ

উত্তর:


125

আমার .bashrc থেকে:

pathadd() {
    if [ -d "$1" ] && [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="${PATH:+"$PATH:"}$1"
    fi
}

দ্রষ্টব্য যে PATH ইতোমধ্যে রফতানি হিসাবে চিহ্নিত করা উচিত, সুতরাং পুনঃবন্দর প্রয়োজন হয় না। ডিরেক্টরিটি যুক্ত করার আগে ডিরেক্টরিটি রয়েছে এবং এটি ডিরেক্টরি রয়েছে কিনা তা এটি পরীক্ষা করে, যা আপনার যত্ন নিতে পারে না।

এছাড়াও, এটি পথের শেষের দিকে নতুন ডিরেক্টরি যুক্ত করে; শুরুতে রাখতে, PATH="$1${PATH:+":$PATH"}"উপরের PATH=লাইনের পরিবর্তে ব্যবহার করুন ।


26
আমি যত্ন করি
ডেনিস উইলিয়ামসন

4
@ নীল: এটি কাজ করে, কারণ এটি ন্যায়বিচারের ":$PATH:"পরিবর্তে তুলনা করে"$PATH"
গর্ডন ডেভিসন

3
@ গর্ডন ডেভিসন: আমি ক্ষমা চাইছি, আমার পরীক্ষাটি ভুল ছিল এবং আপনি সঠিক।
নীল

2
@ গর্ডন ডেভিসন কোঁকড়া বন্ধনীতে স্টাফের বিন্দু কী। আমি এটিকে " ${PATH:+"$PATH:"}$ 1" ধাঁধা দেওয়ার মতো মনে করতে পারি না
নৌকা কোডার

5
@ মার্ক0978: বুকজার নির্দেশিত সমস্যাটি সমাধান করতে আমি এটিই করেছি। ${variable:+value}মানে variableসংজ্ঞায়িত হয়েছে কি না এবং খালি অ-মান রয়েছে কিনা তা পরীক্ষা করে দেখুন এবং যদি এটি মূল্যায়নের ফলাফল দেয় value। মূলত, যদি PATH এটির সাথে সেট করা অবিরাম থাকে তবে এটি সেট করে "$PATH:$1"; যদি এটি ফাঁকা থাকে তবে এটি কেবল এটির জন্য সেট করে "$1"(কোনও কোলনের অভাব নোট করুন)।
গর্ডন ডেভিসন

19

গর্ডন ডেভিসনের উত্তরের সম্প্রসারণ, এটি একাধিক যুক্তি সমর্থন করে

pathappend() {
  for ARG in "$@"
  do
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="${PATH:+"$PATH:"}$ARG"
    fi
  done
}

সুতরাং আপনি পাঠপেন্ডে পাথ 1 পাথ 2 পাথ 3 করতে পারেন ...

প্রিপেন্ডিংয়ের জন্য,

pathprepend() {
  for ((i=$#; i>0; i--)); 
  do
    ARG=${!i}
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="$ARG${PATH:+":$PATH"}"
    fi
  done
}

পাঠপেন্ডের মতো, আপনিও করতে পারেন

প্যাথপ্রিপেন্ড প্যাথ 1 পাথ 2 পাথ 3 ...


3
এটা অসাধারণ! আমি একটি ছোট পরিবর্তন করেছি। 'প্যাথপ্রিপেন্ড' ফাংশনের জন্য, বিপরীতে যুক্তিগুলি পড়া সুবিধাজনক, সুতরাং আপনি উদাহরণস্বরূপ বলতে পারেন pathprepend P1 P2 P3এবং শেষ করতে পারেন PATH=P1:P2:P3। এই আচরণ পেতে, পরিবর্তন for ARG in "$@" doকরার জন্যfor ((i=$#; i>0; i--)); do ARG=${!i}
ইসমাঈল

ধন্যবাদ @ ইশমেল, ভাল পরামর্শ, আমি উত্তরটি সম্পাদনা করেছি। আমি বুঝতে পারি যে আপনার মন্তব্যটি দুই বছরেরও বেশি পুরানো, তবে আমি আর ফিরে আসিনি। আমার ইনবক্সে কীভাবে স্ট্যাক এক্সচেঞ্জ ইমেইলগুলি নামতে হবে তা খুঁজে বের করতে হবে!
গিলাইম পেরেরাউল্ট-আর্চাম্বল্ট

14

এখানে থেকে কিছু আমার উত্তর থেকে এই প্রশ্নের ডগ হ্যারিস 'ফাংশনটি কাঠামো সঙ্গে মিলিত। এটি নিয়মিত অভিব্যক্তি বাশ ব্যবহার করে:

add_to_path ()
{
    if [[ "$PATH" =~ (^|:)"${1}"(:|$) ]]
    then
        return 0
    fi
    export PATH=${1}:$PATH
}

এটি আমার $1পরিবর্তে কেবলমাত্র ব্যবহার করে কাজ করেছিল${1}
আন্দ্রেই

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

10

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

@ গর্ডন-ডেভিসন আমি অপ্রয়োজনীয় উদ্ধৃতি ও উপসংহারের বিশাল অনুরাগী নই। ধরে নিই যে আপনি কোনও বাশ সংস্করণ> = 3 ব্যবহার করছেন, আপনি পরিবর্তে রেগেক্সগুলিতে ব্যাশের বিল্ট ব্যবহার করতে পারেন এবং করতে পারেন:

pathadd() {
    if [ -d "$1" ] && [[ ! $PATH =~ (^|:)$1(:|$) ]]; then
        PATH+=:$1
    fi
}

ডিরেক্টরি বা PATH- তে ফাঁকা স্থান রয়েছে এমন ক্ষেত্রে এটি সঠিকভাবে পরিচালনা করে। রেগেক্স ইঞ্জিনে ব্যাশের তৈরিটি যথেষ্ট ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ছড়িয়ে পড়েছে যা আপনার সংস্করণটির মতো স্ট্রিং কনটেনটেশন এবং ইন্টারপোলেশন তুলনায় কম দক্ষ হতে পারে তা নিয়ে কিছু প্রশ্ন রয়েছে but


1
মন্তব্যগুলি formatting using the backtickকেবল সমর্থন করে তবে আপনি কোনও উপযুক্ত অনুচ্ছেদ নিয়ন্ত্রণ পান না।
নৌকা কোডার

এটি শেষে সংযোজন রাখে। বিদ্যমান অবস্থানগুলিকে ওভাররাইড করার জন্য প্রায়শই শুরুতে যুক্ত করা বাঞ্ছনীয়।
ডেনিস উইলিয়ামসন

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

@ ক্রিস্টোফারস্মিথ - পুনরায়: unnecessary quotingবোঝায় যে আপনি সময়ের আগেই জানতেন যে $PATHশূন্য নয়। "$PATH"PATH নাল কিনা তা ঠিক করে তোলে। একইভাবে যদি $1এমন অক্ষর থাকে যা কমান্ড পার্সারকে বিভ্রান্ত করতে পারে। উদ্ধৃতিগুলিতে রেজেক্স লাগানো এটি "(^|:)$1(:|$)"প্রতিরোধ করে।
জেসি চিশলম

@ জেসি চিসলম: আসলে, আমি বিশ্বাস করি ক্রিস্টোফারের বক্তব্য হ'ল নিয়মগুলি [[এবং এর মধ্যে পৃথক ]]। আমি যতটা সম্ভব উদ্ধৃত করার প্রয়োজন হতে পারে এমন সমস্ত বিষয় উদ্ধৃত করতে পছন্দ করি, যদি না এটির ব্যর্থতা সৃষ্টি হয় তবে আমি বিশ্বাস করি যে তিনি সঠিক, এবং এই উক্তিটির আশেপাশে সত্যই প্রয়োজন নেই$PATH । অন্যদিকে, আমার কাছে মনে হচ্ছে আপনি ঠিকই আছেন $1
স্কট

7
idempotent_path_prepend ()
{
    PATH=${PATH//":$1"/} #delete any instances in the middle or at the end
    PATH=${PATH//"$1:"/} #delete any instances at the beginning
    export PATH="$1:$PATH" #prepend to beginning
}

যখন আপনার $ পথের শুরুতে ঠিক একবারে হাজির হওয়ার জন্য আপনার OME হোম / বিন প্রয়োজন হবে এবং অন্য কোথাও নেই, বিকল্পগুলি গ্রহণ করবেন না।


ধন্যবাদ, এটি একটি দুর্দান্ত মার্জিত সমাধান, তবে আমি পেয়েছি যে এটি কাজ করার জন্য PATH=${PATH/"... পরিবর্তে ... আমাকে করতে হয়েছিল PATH=${PATH//"
মার্ক বুথ

ডাবল-স্ল্যাশ ফর্মটি যেকোন সংখ্যক ম্যাচের সাথে মেলে; একক স্ল্যাশ কেবল প্রথমটির সাথে মেলে (ব্যাশ ম্যান পৃষ্ঠাতে "প্যাটার্ন প্রতিস্থাপনের জন্য অনুসন্ধান করুন")। কেন এটি কাজ করে নি তা নিশ্চিত নয় ...
অ্যান্ডবকলি

এটি অস্বাভাবিক ক্ষেত্রে ব্যর্থ $1হয় যা কেবলমাত্র প্রবেশ (কোনও কলোন নয়)। প্রবেশ দ্বিগুণ হয়ে যায়।
ডেনিস উইলিয়ামসন

এটি পিটার এস 6 জি দ্বারা নির্দেশিত হিসাবে খুব আক্রমণাত্মকভাবে মুছে ফেলা হয় ।
ডেনিস উইলিয়ামসন

6

এখানে এমন একটি বিকল্প সমাধান রয়েছে যাতে রিলান্ড্যান্ট এনট্রেসগুলি অপসারণের অতিরিক্ত সুবিধা রয়েছে:

function pathadd {
    PATH=:$PATH
    PATH=$1${PATH//:$1/}
}

এই ফাংশনটির একক যুক্তিটি PATH- র প্রতি চাপ দেওয়া হয় এবং একই স্ট্রিংয়ের প্রথম উদাহরণটি বিদ্যমান পথ থেকে সরানো হয়। অন্য কথায়, ডিরেক্টরিটি যদি ইতিমধ্যে পথে উপস্থিত থাকে তবে এটি সদৃশ হিসাবে যুক্ত হওয়ার পরিবর্তে সম্মুখ দিকে উন্নীত হয়।

ফাংশনটি সমস্ত প্রবেশের সামনের দিকে একটি কোলন রয়েছে তা নিশ্চিত করার জন্য পথে একটি কোলন প্রিপেন্ড করে এবং তারপরে সেই প্রবেশিকাটি সরিয়ে দিয়ে বিদ্যমান পথে নতুন প্রবেশের প্রিপেন্ডিংয়ের মাধ্যমে কাজ করে। শেষ অংশ বাশের ${var//pattern/sub}স্বরলিপি ব্যবহার করে সঞ্চালিত হয়; দেখতে ব্যাশ ম্যানুয়াল আরো বিস্তারিত জানার জন্য।


ভালো চিন্তা; ত্রুটিযুক্ত বাস্তবায়ন। যদি /home/robertআপনার PATHএবং আপনার মধ্যে ইতিমধ্যে থাকে তবে কী ঘটে তা বিবেচনা করুন pathadd /home/rob
স্কট

5

এখানে আমার (আমি বিশ্বাস করি এটি বহু বছর আগে অস্কার দ্বারা লেখা হয়েছিল, আমার পুরানো ল্যাবের সিসাদমিন, সমস্ত কৃতিত্ব তাঁর কাছে), এটি আমার বর্ষে যুগে যুগে ছিল। এটি আপনাকে নতুন ডিরেক্টরিটি পছন্দ মতো সংযোজন বা সংযোজন করার অনুমতি দেওয়ার অতিরিক্ত সুবিধা রয়েছে:

pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

ব্যবহার:

$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /bin/
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin
$ pathmunge /sbin/ after
$ echo $PATH
/bin/:/usr/local/bin/:/usr/bin:/sbin/

5

প্রিপেন্ডিংয়ের জন্য, আমি রাসেলের সমাধানটি পছন্দ করি তবে একটি ছোট বাগ রয়েছে: আপনি যদি "/ বিন" এর মতো "/ এসবিন: / ইউএসআর / বিন: / ভার / ইউএসআর / বিন: / ইউএসআর / স্থানীয় কিছু চালানোর চেষ্টা করেন তবে / বিন: / usr / sbin "এটি প্রতিস্থাপন করে" / বিন: "3 বার (যখন এটি সত্যই মিলেনি)। @ গর্ডন-ডেভিসনের কাছ থেকে সংযোজন সমাধানের সাথে এর জন্য একটি সংমিশ্রণ, আমি এটি পেয়েছি:

path_prepend() {
    if [ -d "$1" ]; then
        PATH=${PATH//":$1:"/:} #delete all instances in the middle
        PATH=${PATH/%":$1"/} #delete any instance at the end
        PATH=${PATH/#"$1:"/} #delete any instance at the beginning
        PATH="$1${PATH:+":$PATH"}" #prepend $1 or if $PATH is empty set to $1
    fi
}

4

নীচের মত একটি সাধারণ উপন্যাসটি কৌশলটি করা উচিত:

alias checkInPath="echo $PATH | tr ':' '\n' | grep -x -c "

এটি যা কিছু করে তা হ'ল পথটি বিভক্ত করা হয়: আপনি যে আর্গুমেন্টটি প্রবেশ করেন তার বিপরীতে প্রতিটি উপাদানকে তুলনা করুন gre একটি সম্পূর্ণ লাইন ম্যাচের জন্য গ্রেপ চেক করুন এবং গণনাটি মুদ্রণ করুন।

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

$ checkInPath "/usr/local"
1
$ checkInPath "/usr/local/sbin"
1
$ checkInPath "/usr/local/sbin2"
0
$ checkInPath "/usr/local/" > /dev/null && echo "Yes" || echo "No"
No
$ checkInPath "/usr/local/bin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin" > /dev/null && echo "Yes" || echo "No"
Yes
$ checkInPath "/usr/local/sbin2" > /dev/null && echo "Yes" || echo "No"
No

ইকো কমান্ডটি অ্যাডপোপথ বা কিছু অনুরূপ উপকরণ / ফাংশন দিয়ে প্রতিস্থাপন করুন।


"গ্রেপ-এক্স" ব্যবহার করা আমার ব্যাশ ফাংশনে আমি যে লুপটি রেখেছি তার চেয়ে সম্ভবত দ্রুত।
ডগ হ্যারিস


2

এখানে আমি বেত্রাঘাত করেছি:

add_to_path ()
{
    path_list=`echo $PATH | tr ':' ' '`
    new_dir=$1
    for d in $path_list
    do
        if [ $d == $new_dir ]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}

এখন .Bashrc এ আমার আছে:

add_to_path /usr/local/mysql/bin

আমার আসল স্থানগুলি কীভাবে ডিরেক্টরি পরিচালনা করবে না সে সম্পর্কে মন্তব্য করার পরে আপডেট করা সংস্করণ ( আমাকে ব্যবহারের দিকে নির্দেশ করার জন্য এই প্রশ্নের জন্য ধন্যবাদ IFS):

add_to_path ()
{
    new_dir=$1
    local IFS=:
    for d in $PATH
    do
        if [[ "$d" == "$new_dir" ]]
        then
            return 0
        fi
    done
    export PATH=$new_dir:$PATH
}

1
এই ব্যর্থ হতে পারে যদি থাকে ডিরেক্টরির নাম ইতিমধ্যেই PATHহোয়াইটস্পেস রয়েছে, *, ?, অথবা [... ]
স্কট

ভাল কথা ... তবে আমি একজন পুরাতন স্কুলের লিনাক্স লোক এবং এর মধ্যে কখনও সাদা অংশের জন্য কোনও পথ ব্যবহার করব না :-)
ডগ হ্যারিস

তাদের নামে সাদা জায়গা দিয়ে জিনিস তৈরি না করার জন্য আপনার পক্ষে ভাল। এমন কোড লেখার জন্য আপনাকে লজ্জা দেয় যা সেগুলি উপস্থিত থাকতে পারে না। এবং "পুরাতন-স্কুল লিনাক্স লোক" এর সাথে কী করার আছে? উইন্ডোজ ধারণাটি জনপ্রিয় করে তুলতে পারে (আপনাকে ধন্যবাদ, Documents and Settingsএবং Program Files), তবে ইউনিক্স উইন্ডোজটির অস্তিত্বের আগে থেকেই হোয়াইটস্পেস সম্বলিত পথের নামগুলি সমর্থন করে
স্কট

2

আমি কিছুটা অবাক হয়েছি যে এখনও কেউ এটির কথা উল্লেখ করেনি, তবে আপনি readlink -fআপেক্ষিক পাথগুলিকে পরম পথে রূপান্তর করতে এবং সেগুলিকে PATH এ যুক্ত করতে পারেন।

উদাহরণস্বরূপ, গিলিয়াম পেরেলাউল্ট-আর্চাম্বল্টের উত্তরে উন্নতি করতে,

pathappend() {
  for ARG in "$@"
  do
    if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
        PATH="${PATH:+"$PATH:"}$ARG"
    fi
  done
}

হয়ে

pathappend() {
    for ARG in "$@"
    do
        if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
        then
            if ARGA=$(readlink -f "$ARG")               #notice me
            then
                if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
                then
                    PATH="${PATH:+"$PATH:"}$ARGA"
                fi
            else
                PATH="${PATH:+"$PATH:"}$ARG"
            fi
        fi
    done
}

1. মূল বিষয়গুলি - এটি কী ভাল করে?

readlink -fকমান্ড (অন্যান্য বিষয় ছাড়াও) একটি সুনির্দিষ্ট পাথ করার জন্য একটি আপেক্ষিক পাথ রূপান্তরিত করবে। এটি আপনাকে এমন কিছু করতে দেয়

$ সিডি / পাথ / টু / আমার / বিন / দির
$ পাঠপেন্ড 
$ প্রতিধ্বনি "AT পথ"
<আপনার_পরে_পথ> : / পথ / থেকে / আমার / বিন / দির

২. আমরা দু'বার পথের পরীক্ষার জন্য কেন পরীক্ষা করি?

ঠিক আছে, উপরের উদাহরণ বিবেচনা করুন। যদি ব্যবহারকারী দ্বিতীয়বার ডিরেক্টরি থেকে বলেন , হবে । অবশ্যই উপস্থিত হবে না । কিন্তু তারপর সেট করা হবে (এর সঠিক পথটি সমতুল্য ), যা হয় আগে থেকেই । সুতরাং আমরা যোগ এড়িয়ে চলতে হবে থেকে একটি দ্বিতীয় সময়।pathappend ./path/to/my/bin/dirARG..PATHARGA/path/to/my/bin/dir.PATH/path/to/my/bin/dirPATH

সম্ভবত আরও গুরুত্বপূর্ণভাবে, এর প্রাথমিক উদ্দেশ্যটি readlinkহ'ল এটির নাম অনুসারে প্রতীকী লিঙ্কটি দেখতে এবং এতে থাকা পথের নামটি পড়তে হবে (অর্থাত্ পয়েন্টগুলি)। উদাহরণ স্বরূপ:

$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx  1   root   root    Sep  3  2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2

এখন, যদি আপনি বলেন pathappend /usr/lib/perl/5.14, এবং আপনার ইতিমধ্যে /usr/lib/perl/5.14আপনার পথের মধ্যে আছে , ভাল, ভাল; আমরা ঠিক যেমন এটি রেখে দিতে পারি। কিন্তু, যদি /usr/lib/perl/5.14আপনার পাথ ইতিমধ্যে নয়, আমরা কল readlinkএবং পেতে ARGA= /usr/lib/perl/5.14.2, এবং তারপর আমরা যোগ যে করতে PATH। তবে এক মিনিট অপেক্ষা করুন - যদি আপনি ইতিমধ্যে বলে থাকেন pathappend /usr/lib/perl/5.14তবে /usr/lib/perl/5.14.2আপনার প্যাথএলটি ইতিমধ্যে রয়েছে এবং এটি আবার PATHদ্বিতীয়বার এড়াতে আমাদের এটিকে পরীক্ষা করতে হবে ।

৩. ডিল কী if ARGA=$(readlink -f "$ARG")?

যদি এটি অস্পষ্ট থাকে তবে এই লাইনটি readlinkসফল হয় কিনা তা পরীক্ষা করে । এটি কেবল ভাল, রক্ষণাত্মক প্রোগ্রামিং অনুশীলন। যদি আমরা কমান্ড এম থেকে আউটপুট ব্যবহার করতে যাচ্ছি  কমান্ড  এন (যেখানে এম  <  এন ) এর অংশ হিসাবে , কমান্ড এম ব্যর্থ হয়েছে কিনা তা পরীক্ষা করে দেখার এবং এটি কোনওভাবে হ্যান্ডেল করা বুদ্ধিমানের কাজ  । আমি মনে করি না এটি সম্ভবত ব্যর্থ হবে - তবে ওএস এক্স এবং অন্য কোথাও একটি স্বেচ্ছাসেবীর ফাইলের নিখুঁত পথটি কীভাবে পুনরুদ্ধার করবেন তা আলোচিত , এটি একটি জিএনইউ আবিষ্কার is এটি পসিক্সে নির্দিষ্ট করা হয়নি, সুতরাং ম্যাক ওএস, সোলারিস এবং অন্যান্য নন-লিনাক্স ইউনিক্সগুলিতে এর উপস্থিতি প্রশ্নবিদ্ধ। (আসলে, আমি কেবল একটি মন্তব্য পড়েছি যা এতে বলে “readlinkreadlinkreadlink -fম্যাক ওএস এক্স 10.11.6 এ কাজ করছে বলে মনে হয় না, তবে realpathবাক্স থেকে কাজ করে ”" সুতরাং, আপনি যদি এমন কোনও সিস্টেমে থাকেন readlinkযেখানে readlink -fনেই বা যেখানে কাজ করে না, আপনি এটি সংশোধন করতে সক্ষম হতে পারেন স্ক্রিপ্টটি ব্যবহার করতে হবে realpath)

অবশ্যই, আপনি যদি এমন কোনও সিস্টেমে থাকেন যা readlink(বা  realpath) নেই তবে আপনি করতে চান না ।pathappend .

দ্বিতীয় -dপরীক্ষা ( [ -d "$ARGA" ]) সম্ভবত অপ্রয়োজনীয়। আমি এমন কোনও দৃশ্যের কথা ভাবতে পারি না যেখানে $ARGডিরেক্টরি রয়েছে এবং readlinkসফল হয় তবে  $ARGAকোনও ডিরেক্টরি নয়। আমি কেবল ifতৃতীয়টি তৈরির জন্য প্রথম বিবৃতিটি অনুলিপি করে আটকে দিয়েছি -dএবং অলসতার বাইরে আমি পরীক্ষাটি রেখেছি  ।

4. অন্য কোন মন্তব্য?

হ্যাঁ। এখানে অন্যান্য অনেক জবাবের মতো, এটি একটি পরীক্ষা করে প্রতিটি আর্গুমেন্ট ডিরেক্টরি হয় কিনা, এটি যদি থাকে তবে এটি প্রক্রিয়া করে এবং তা না থাকলে তা এড়িয়ে যায়। আপনি যদি pathappend কেবলমাত্র " ." ফাইল (যেমন .bash_profileএবং .bashrc) এবং অন্যান্য স্ক্রিপ্টগুলিতে ব্যবহার করেন তবে এটি (বা নাও) পর্যাপ্ত হতে পারে । তবে, যেমন এই উত্তরটি (উপরে) দেখিয়েছে, ইন্টারেক্টিভভাবে এটি ব্যবহার করা একেবারে সম্ভাব্য। আপনি যদি খুব অবাক হন

$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found

আপনি লক্ষ্য করেছেন য়ে আমি বলেছিলাম nysql মধ্যে pathappendকমান্ড বদলে mysql? এবং এটি pathappendকিছুই বলেনি; এটা কি চুপচাপ ভুল যুক্তি উপেক্ষা?

আমি উপরে বলেছি ত্রুটিগুলি পরিচালনা করা ভাল অনুশীলন। এখানে একটি উদাহরণ:

pathappend() {
    for ARG in "$@"
    do
        if [ -d "$ARG" ]
        then
            if [[ ":$PATH:" != *":$ARG:"* ]]
            then
                if ARGA=$(readlink -f "$ARG")           #notice me
                then
                    if [[ ":$PATH:" != *":$ARGA:"* ]]
                    then
                        PATH="${PATH:+"$PATH:"}$ARGA"
                    fi
                else
                    PATH="${PATH:+"$PATH:"}$ARG"
                fi
            fi
        else
            printf "Error: %s is not a directory.\n" "$ARG" >&2
        fi
    done
}

(1) আপনার উদ্ধৃতি যুক্ত করা উচিত : readlink -f "$ARG". (২) কেন হবে তা আমি জানি না (বিশেষত -d "$ARG"পরীক্ষাটি সাফল্যের পরে ) তবে আপনি readlinkব্যর্থ হয়েছেন কিনা তা পরীক্ষা করতে চাইতে পারেন । (3) আপনি readlink"আসল ফাইলের নাম" - তে প্রতীকী লিঙ্কের নামটি ম্যাপ করার জন্য আপনার প্রাথমিক ফাংশনটি উপেক্ষা করছেন বলে মনে হচ্ছে । যদি (উদাহরণস্বরূপ) এর /binপ্রতীকী লিঙ্ক হয় /bin64, তবে বার বার কল করার pathappend /binফলে PATH বলার ফলস্বরূপ …:/bin64:/bin64:/bin64:/bin64:…। আপনার সম্ভবত (এটিও) পরীক্ষা করা উচিত যে এর নতুন মান $ARGইতিমধ্যে রয়েছে কিনা PATH
স্কট

(1) ভাল পর্যবেক্ষণ, আমি এটি স্থির। (২) কোন ক্ষেত্রে রিডলিঙ্ক ব্যর্থ হবে? ধরে নিচ্ছি যে কোনও পথ সঠিক এবং এটি একটি কার্যকর অবস্থানকে বোঝায়। (3) আমি নিশ্চিত নই যে রিডলিঙ্কের প্রাথমিক ফাংশনটি কোনটি নির্দেশ করে, আমি বিশ্বাস করি ইউনিক্স ফাইল সিস্টেমের বেশিরভাগ (সমস্ত যদি না?) পাথগুলিকে 2 ধরণের লিঙ্ক, প্রতীকী লিঙ্ক এবং হার্ড লিঙ্কগুলিতে ভাগ করা যায়। সদৃশ পথে প্রবেশের ক্ষেত্রে আপনি ঠিক বলেছেন তবে আমার উত্তরটির উদ্দেশ্যটি এটি যুক্ত করা হয়নি (যেমন আমি লক্ষ্য করেছি যে অন্যান্য উত্তর ইতিমধ্যে এটি উল্লেখ করেছে)। আমি আর একটি উত্তর যুক্ত করার একমাত্র কারণ হ'ল এমন কিছু অবদানের জন্য যা আমি ভেবেছিলাম যে ইতিমধ্যে অবদান ছিল না
qwertyzw

(২) আমি বলতে চাইছি, যদি কমপক্ষে কম্যান্ডের নামটি তার উদ্দেশ্যটিতে অন্তর্নিহিত / ইঙ্গিত দেয় তবে পঠন লিঙ্কে 'লিঙ্ক' শক্ত বা নরম লিঙ্কগুলিকে বোঝায়। তবে আপনি ঠিক বলেছেন: ম্যান রিডলিংক বলেছেন 'রিডলিংক - সমাধান করা প্রতীকী লিঙ্কগুলি বা ক্যানোনিকাল ফাইলের নাম মুদ্রণ করুন', .আমার যে উদাহরণটিতে আমি বিশ্বাস করি তা একটি ক্যানোনিকাল ফাইলের নাম হিসাবে বিবেচিত হতে পারে। সঠিক?
কিওয়ারটিজডাব্লু

(1) প্রতীকী লিঙ্কগুলি বোঝে এমন লোকদের কাছে, readlinkএর নামটি এর উদ্দেশ্যটি পরিষ্কারভাবে বোঝায় - এটি একটি প্রতীকী লিঙ্কটি দেখায় এবং এতে থাকা পথের নামটি পড়ে (যেমন, পয়েন্টগুলি) পাঠ করে। (২) আচ্ছা, আমি বলেছিলাম যে কেন আমি readlinkব্যর্থ হব জানি না । আমি সাধারণ বক্তব্যটি দিয়েছিলাম যে কোনও স্ক্রিপ্ট বা ফাংশনে যদি একাধিক কমান্ড থাকে এবং কমান্ড  এন বিপর্যয়করভাবে ব্যর্থ হওয়ার গ্যারান্টিযুক্ত হয় (বা মোটেও বোঝা যায় না) যদি কমান্ড  এম ব্যর্থ হয় (যেখানে এম  <  এন ) হয় তবে এটি বুদ্ধিমানের অনুশীলন কমান্ড এম ব্যর্থ হয়েছে কিনা তা পরীক্ষা করে দেখুন এবং কোনওভাবে এটি পরিচালনা করছেন - খুব কমপক্ষে,… (চালিয়ে যান)
স্কট

(চালিয়ে যাওয়া) ... ডায়গনিস্টিক সহ স্ক্রিপ্ট / ফাংশন বাতিল করুন। Hypothetically, readlinkব্যর্থ হতে পারে যদি (ক) নির্দেশিকাতে আপনার কলের মধ্যে নতুন নামকরণ বা (অন্য প্রক্রিয়া দ্বারা) মোছা হয়েছে testএবং readlink, অথবা (খ) যদি /usr/bin/readlinkমোছা হয়েছে (অথবা বিকৃত)। (৩) আপনি আমার বক্তব্য মিস করছেন বলে মনে হচ্ছে। আমি আপনাকে অন্যান্য উত্তর (গুলি) নকল করতে উত্সাহিত করছি না; আমি বলছি যে, ARGকমান্ড লাইন থেকে মূল (কমান্ড লাইন থেকে) ইতিমধ্যে রয়েছে কিনা তা যাচাই করে PATH, তবে নতুনটির (আউটপুট ) চেকটি পুনরাবৃত্তি না করে আপনার উত্তরটি অসম্পূর্ণ এবং তাই ভুল। … (চালিয়ে যাওয়া)ARGreadlink
স্কট ২

1
function __path_add(){  
if [ -d "$1" ] ; then  
    local D=":${PATH}:";   
    [ "${D/:$1:/:}" == "$D" ] && PATH="$PATH:$1";  
    PATH="${PATH/#:/}";  
    export PATH="${PATH/%:/}";  
fi  
}  

1

এই উপায়টি ভাল কাজ করে:

if [[ ":$PATH:" != *":/new-directory:"* ]]; then PATH=${PATH}:/new-directory; fi

0

আমার সংস্করণগুলি খালি পাথ সম্পর্কে কম সতর্কতা অবলম্বন করছে এবং কয়েকটি পোস্ট করার চেয়ে পাথগুলি বৈধ এবং ডিরেক্টরি হওয়ার জন্য জোর দিচ্ছে, তবে আমি প্রিপেন্ড / অ্যাপেন্ড / ক্লিন / অনন্য-ইফআই / ইত্যাদির একটি বৃহত-ইশ সংগ্রহ পেয়েছি। শেল ফাংশন পাথ হেরফের জন্য দরকারী পুরো লটটি তাদের বর্তমান অবস্থায় এখানে রয়েছে: http://pastebin.com/xS9sgQsX (প্রতিক্রিয়া এবং উন্নতিগুলি আপনাকে স্বাগত জানায়!)


0

আপনি পার্ল ওয়ান লাইনার ব্যবহার করতে পারেন:

appendPaths() { # append a group of paths together, leaving out redundancies
    # use as: export PATH="$(appendPaths "$PATH" "dir1" "dir2")
    # start at the end:
    #  - join all arguments with :,
    #  - split the result on :,
    #  - pick out non-empty elements which haven't been seen and which are directories,
    #  - join with :,
    #  - print
    perl -le 'print join ":", grep /\w/ && !$seen{$_}++ && -d $_, split ":", join ":", @ARGV;' "$@"
}

এখানে এটি বাশ:

addToPath() { 
    # inspired by Gordon Davisson, http://superuser.com/a/39995/208059
    # call as: addToPath dir1 dir2
    while (( "$#" > 0 )); do
    echo "Adding $1 to PATH."
    if [[ ! -d "$1" ]]; then
        echo "$1 is not a directory.";
    elif [[ ":$PATH:" == *":$1:"* ]]; then
        echo "$1 is already in the path."
    else
            export PATH="${PATH:+"$PATH:"}$1" # ${x:-defaultIfEmpty} ${x:+valueIfNotEmpty}
    fi
    shift
    done
}

0

আমি যদি কিছু সরবরাহ না করা হয় তবে বর্তমান দিরটি ব্যবহার করতে গর্ডন ডেভিসনের উত্তরকে কিছুটা সংশোধন করেছি । সুতরাং আপনি paddযে ডিরেক্টরিটি আপনার পাথের সাথে যুক্ত করতে চান তা কেবল আপনি করতে পারেন ।

padd() {
  current=`pwd`
  p=${1:-$current}
  if [ -d "$p" ] && [[ ":$PATH:" != *":$p:"* ]]; then
      PATH="$p:$PATH"
  fi
}

0

কোনও কাস্টম ভেরিয়েবল সেট করা হয়েছে কিনা তা আপনি পরীক্ষা করতে পারেন, অন্যথায় এটি সেট করুন এবং তারপরে নতুন এন্ট্রি যুক্ত করুন:

if [ "$MYPATHS" != "true" ]; then
    export MYPATHS="true"
    export PATH="$PATH:$HOME/bin:"

    # java stuff
    export JAVA_HOME="$(/usr/libexec/java_home)"
    export M2_HOME="$HOME/Applications/apache-maven-3.3.9"
    export PATH="$JAVA_HOME/bin:$M2_HOME/bin:$PATH"

    # etc...
fi

অবশ্যই, অন্য কোনও স্ক্রিপ্ট দ্বারা যুক্ত করা থাকলে এই এন্ট্রিগুলি এখনও নকল করা যেতে পারে /etc/profile


0

এই স্ক্রিপ্টটি আপনাকে শেষে যোগ করতে দেয় $PATH:

PATH=path2; add_to_PATH after path1 path2:path3
echo $PATH
path2:path1:path3

বা এর শুরুতে যুক্ত করুন $PATH:

PATH=path2; add_to_PATH before path1 path2:path3
echo $PATH
path1:path3:path2

# Add directories to $PATH iff they're not already there
# Append directories to $PATH by default
# Based on https://unix.stackexchange.com/a/4973/143394
# and https://unix.stackexchange.com/a/217629/143394
add_to_PATH () {
  local prepend  # Prepend to path if set
  local prefix   # Temporary prepended path
  local IFS      # Avoid restoring for added laziness

  case $1 in
    after)  shift;; # Default is to append
    before) prepend=true; shift;;
  esac

  for arg; do
    IFS=: # Split argument by path separator
    for dir in $arg; do
      # Canonicalise symbolic links
      dir=$({ cd -- "$dir" && { pwd -P || pwd; } } 2>/dev/null)
      if [ -z "$dir" ]; then continue; fi  # Skip non-existent directory
      case ":$PATH:" in
        *":$dir:"*) :;; # skip - already present
        *) if [ "$prepend" ]; then
           # ${prefix:+$prefix:} will expand to "" if $prefix is empty to avoid
           # starting with a ":".  Expansion is "$prefix:" if non-empty.
            prefix=${prefix+$prefix:}$dir
          else
            PATH=$PATH:$dir  # Append by default
          fi;;
      esac
    done
  done
  [ "$prepend" ] && PATH=$prefix:$PATH
}

0

এখানে একটি পসিক্স-আনুগত্যের উপায়।

# USAGE: path_add [include|prepend|append] "dir1" "dir2" ...
#   prepend: add/move to beginning
#   append:  add/move to end
#   include: add to end of PATH if not already included [default]
#          that is, don't change position if already in PATH
# RETURNS:
# prepend:  dir2:dir1:OLD_PATH
# append:   OLD_PATH:dir1:dir2
# If called with no paramters, returns PATH with duplicate directories removed
path_add() {
    # use subshell to create "local" variables
    PATH="$(path_unique)"
    export PATH="$(path_add_do "$@")"
}

path_add_do() {
    case "$1" in
    'include'|'prepend'|'append') action="$1"; shift ;;
    *)                            action='include'   ;;
    esac

    path=":$PATH:" # pad to ensure full path is matched later

    for dir in "$@"; do
        #       [ -d "$dir" ] || continue # skip non-directory params

        left="${path%:$dir:*}" # remove last occurrence to end

        if [ "$path" = "$left" ]; then
            # PATH doesn't contain $dir
            [ "$action" = 'include' ] && action='append'
            right=''
        else
            right=":${path#$left:$dir:}" # remove start to last occurrence
        fi

        # construct path with $dir added
        case "$action" in
            'prepend') path=":$dir$left$right" ;;
            'append')  path="$left$right$dir:" ;;
        esac
    done

    # strip ':' pads
    path="${path#:}"
    path="${path%:}"

    # return
    printf '%s' "$path"
}

# USAGE: path_unique [path]
# path - a colon delimited list. Defaults to $PATH is not specified.
# RETURNS: `path` with duplicated directories removed
path_unique() {
    in_path=${1:-$PATH}
    path=':'

    # Wrap the while loop in '{}' to be able to access the updated `path variable
    # as the `while` loop is run in a subshell due to the piping to it.
    # https://stackoverflow.com/questions/4667509/shell-variables-set-inside-while-loop-not-visible-outside-of-it
    printf '%s\n' "$in_path" \
    | /bin/tr -s ':' '\n'    \
    | {
            while read -r dir; do
                left="${path%:$dir:*}" # remove last occurrence to end
                if [ "$path" = "$left" ]; then
                    # PATH doesn't contain $dir
                    path="$path$dir:"
                fi
            done
            # strip ':' pads
            path="${path#:}"
            path="${path%:}"
            # return
            printf '%s\n' "$path"
        }
}

এটি এই প্রশ্নটির উত্তর এবং মাইক 511 এর উত্তর এখানে গিলিয়াম পেরেলাউল্ট -আর্চাম্বল্টের উত্তর থেকে আঁকছে

আপডেট করুন 2017-11-23: @ স্কট প্রতি স্থির বাগ


আমি একটি পূর্বনির্ধারিত সাথে প্রিপেন্ডিং এবং পোস্টিং (সংযোজন) এর মধ্যে চয়ন করার জন্য একটি কমান্ড-লাইন বিকল্প সরবরাহ করার জন্য এটি উপস্থাপন করতে যাচ্ছি। তবে আমি ভেবেছিলাম: এটি কোনও ব্যাখ্যা ছাড়াই কিছুটা গুপ্ত কোড of (এবং সত্য আপনি দুই ফাংশন আছে, এক যেখানে পাথ পরিবর্তন এবং তার নতুন মান প্রতিধ্বনি, এবং অন্যান্য ধারন করে যে আউটপুট এবং এটা পথে আবার নির্ধারণ , (Cont'd) শুধু একটি অপ্রয়োজনীয় জটিলতা হয়।) ...
স্কট

(চালিয়ে যাওয়া) ... এবং তারপরে আমি লক্ষ্য করেছি যে লিঙ্কগুলি ভুল ছিল। (এবং আমি নিশ্চিত না যে আপনি কেন এই লোকগুলিকে দোষ দিচ্ছেন; আপনি তাদের উত্তরগুলি থেকে খুব বেশি অনুলিপি করেছেন বলে মনে হয় না)) এবং তখন আমি লক্ষ্য করেছি যে কোডটি ভুল ছিল। আমি অনুমান করি যে এটি একটি সুপথিত পাঠ্য রক্ষণাবেক্ষণের জন্য একটি ঠিক কাজ করেছে , তবে এর কোনও গ্যারান্টি নেই যে এটি ইতিমধ্যে সু-গঠিত, বিশেষত যদি আপনি বিদ্যুতচেতন করেন না /etc/profile। আপনি যে ডিরেক্টরিটি PATH এ যুক্ত করতে চাইছেন সেটি ইতিমধ্যে একাধিকবার থাকতে পারে এবং আপনার কোডটি সেটির উপরে চাপ দেয়। … (চালিয়ে যাওয়া)
স্কট

(Cont'd) ... উদাহরণস্বরূপ, যদি আপনি পূর্বে লিখুন চেষ্টা /a/ckকরতে /b:/a/ck:/tr:/a/ck, আপনি পেতে /a/ck:/b:/a/ck:/tr:/tr:/a/ck
স্কট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.