আপনি বাশে কোনও ফাইলের পথকে কীভাবে সাধারণীকরণ করবেন?


203

আমি রূপান্তর /foo/bar/..করতে চাই/foo

এখানে কি কোনও বাশ আদেশ আছে?


সম্পাদনা করুন: আমার ব্যবহারিক ক্ষেত্রে ডিরেক্টরিটি বিদ্যমান।


4
এটা কোন ব্যাপার হয়, তাহলে /foo/barবা এমনকি /fooআসলে অস্তিত্ব, অথবা আপনি শুধুমাত্র পথ নাম নিয়ম অনুযায়ী স্ট্রিং ম্যানিপুলেশন দৃষ্টিভঙ্গি আগ্রহী?
চেন লেভি

5
@ টাটবার্গ ... এটাই তো সম্মতিযুক্ত ...
ক্যামিলো মার্টিন

2
@ ক্যামিলোমার্টিন একেবারেই সংশ্লেষিত নয় - প্রশ্নটি যা বলে তা ঠিক তাই করে - রূপান্তর /foo/bar/..করে /fooএবং একটি bashআদেশ ব্যবহার করে । যদি অন্য প্রয়োজনীয়তাগুলিও বলা হয় না, তবে সম্ভবত সেগুলি হওয়া উচিত ...
twalberg

14
@ টটলবার্গ আপনি অনেক বেশি টিডিডি -_- 'করছেন
ক্যামিলো মার্টিন

উত্তর:


192

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

dirname /foo/bar/baz 
# /foo/bar 
basename /foo/bar/baz
# baz
dirname $( dirname  /foo/bar/baz  ) 
# /foo 
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp

realpath বিকল্প

যদি realpathআপনার শেল সমর্থন করে না, আপনি চেষ্টা করতে পারেন

readlink -f /path/here/.. 

এছাড়াও

readlink -m /path/there/../../ 

হিসাবে একই কাজ করে

realpath -s /path/here/../../

সেই পথে স্বাভাবিক হওয়ার জন্য পথটির অস্তিত্বের প্রয়োজন নেই।


5
ওএস এক্স সমাধানের জন্য আপনারা কীসের জন্য নীচে অ্যাডাম লিসের উত্তরটি দেখুন।
ট্রেনটন

stackoverflow.com/a/17744637/999943 এটি একটি দৃ strongly ়ভাবে সম্পর্কিত উত্তর! আমি এই কিউএ পোস্টগুলির উভয়ই একদিনে এসেছি এবং আমি সেগুলি লিঙ্ক করতে চেয়েছিলাম।
ফায়াত

রিয়েলপ্যাথটি 2012 সালে কোর্টিলগুলিতে যুক্ত হয়েছে বলে মনে হয় g github.com/coreutils/coreutils/commits/master/src/relpath.c এ ফাইলের ইতিহাস দেখুন ।
নোহ Lavine

1
উভয়ই realpathএবং readlinkজিএনইউ মূল ইউটিলিটিগুলি থেকে আসে, সম্ভবত সম্ভবত আপনি উভয়ই পাবেন না কোনও একটিই পাবেন। যদি আমি সঠিকভাবে মনে রাখি তবে ম্যাকের পঠন লিঙ্ক সংস্করণটি জিএনইউর চেয়ে কিছুটা আলাদা: - :12
এন্টোইন 'হাশর' মুসো

100

এটি করার জন্য সরাসরি বাশ কমান্ড আছে কিনা তা আমি জানি না, তবে আমি সাধারণত করি

normalDir="`cd "${dirToNormalize}";pwd`"
echo "${normalDir}"

এবং এটি ভাল কাজ করে।


9
এটি স্বাভাবিক হবে তবে নরম লিঙ্কগুলি সমাধান করবে না। এটি কোনও বাগ বা কোনও বৈশিষ্ট্য হতে পারে। :-)
আদম লিস

4
যদি a সিডিপ্যাথ সংজ্ঞায়িত হয় তবে এটিতেও সমস্যা রয়েছে; কারণ "সিডি foo" যে কোনও "foo" ডিরেক্টরিতে স্যুইচ করবে যা বর্তমান ডিরেক্টরিতে থাকা "foo" নয়, $ CDPATH এর একটি উপ-ডিরেক্টরি। আমার মনে হয় আপনার এমন কিছু করা দরকার: CDPATH = "" সিডি "$ ir dirToNormalize}" && pwd -P।
এমজেএস

7
টিমের উত্তর অবশ্যই সহজতম এবং বহনযোগ্য। সিডিপিএইচটি সহজেই মোকাবেলা করা যায়: দির = "$ (সিডিপ্যাট && সিডি আনসেট না করে" $ দির "এবং&ww)"
ডেভিড ব্লাভিনস

2
এটি খুব বিপজ্জনক হতে পারে ( rm -rf $normalDir) যদি ডিআরটোএনরালাইমাইজ উপস্থিত না থাকে!
ফ্রাঙ্ক মুলিউনার

4
হ্যাঁ, &&@ ডেভিডব্লেইনস এর মন্তব্য অনুসারে একটি ব্যবহার করা ভাল best
ইলিয়াস ডরনেলেস

54

ব্যবহার করে দেখুন realpath। নীচে এর সম্পূর্ণরূপে উত্স রয়েছে, এর মাধ্যমে পাবলিক ডোমেনে অনুদান দেওয়া হয়েছে।

// realpath.c: display the absolute path to a file or directory.
// Adam Liss, August, 2007
// This program is provided "as-is" to the public domain, without express or
// implied warranty, for any non-profit use, provided this notice is maintained.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>   
#include <limits.h>

static char *s_pMyName;
void usage(void);

int main(int argc, char *argv[])
{
    char
        sPath[PATH_MAX];


    s_pMyName = strdup(basename(argv[0]));

    if (argc < 2)
        usage();

    printf("%s\n", realpath(argv[1], sPath));
    return 0;
}    

void usage(void)
{
    fprintf(stderr, "usage: %s PATH\n", s_pMyName);
    exit(1);
}

1
এটি কি স্ট্যান্ডার্ড বাশ ইনস্টলের অংশ হিসাবে অন্তর্ভুক্ত? আমি আমাদের সিস্টেমে "কমান্ড পাওয়া যায় নি" (আরএইচইএলে 3.00.15 (1) বাশ)
টিম হুইটকম্ব

4
gnu.org/software/coreutils : readlink জন্য, কিন্তু realpath এই প্যাকেজ থেকে আসে packages.debian.org/unstable/utils/realpath
কেন্ট Fredric

8
এটি উবুন্টু / বিএসডি-তে মানক,
সেন্টোস

4
"বোনাস: এটি একটি বাশ কমান্ড, এবং সর্বত্র উপলভ্য!" দিয়ে আপনার অংশটি সত্যই স্ট্রাইক করা উচিত! অংশ সম্পর্কে realpath। এটি আমার প্রিয় হিসাবেও ঘটে, তবে উত্স থেকে আপনার সরঞ্জামটি সংকলন করার পরিবর্তে। এটি সবই হেভিওয়েটের জন্য, এবং বেশিরভাগ সময় আপনি কেবল চান readlink -f... বিটিডাব্লু, readlinkএটি কোনও বাশ বিল্টিন নয়, তবে coreutilsউবুন্টুর অংশ ।
টমাসজ গ্যান্ডোর

4
আপনি বলেছিলেন যে আপনি এটি পাবলিক ডোমেনে অনুদান দিচ্ছেন, তবে শিরোনামটি "কোনও অলাভজনক ব্যবহারের জন্য "ও বলেছেন - আপনি কি সত্যই এটি পাবলিক ডোমেনে অনুদান দেওয়ার অর্থ? এর অর্থ
হ'ল

36

একটি বহনযোগ্য এবং নির্ভরযোগ্য সমাধান হ'ল পাইথন ব্যবহার করা, যা সর্বত্র (ডারউইন সহ) সর্বত্র ইনস্টল করা আছে। আপনার দুটি বিকল্প রয়েছে:

  1. abspath একটি নিখুঁত পথ ফেরত দেয় তবে প্রতিলিঙ্কগুলি সমাধান করে না:

    python -c "import os,sys; print(os.path.abspath(sys.argv[1]))" path/to/file

  2. realpath একটি নিখুঁত পাথ ফিরে আসে এবং এটি করার ফলে একটি প্রচলিত পথ উত্পন্ন করে প্রতীকগুলি সমাধান করে:

    python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" path/to/file

প্রতিটি ক্ষেত্রে, path/to/fileহয় আপেক্ষিক বা পরম পথ হতে পারে।


7
ধন্যবাদ, এটিই কেবল কাজ করেছিল। ওএস এক্স এর অধীনে রিডলিঙ্ক বা রিয়েলপথ উপলভ্য নয় Py পাইথন বেশিরভাগ প্ল্যাটফর্মে থাকা উচিত।
sorin

1
কেবল পরিষ্কার করার জন্য, অপশনটি readlinkদিয়ে নয়, ওএস এক্সে উপলব্ধ -f। পোর্টেবল কাজের ক্ষেত্রগুলি এখানে আলোচনা করা হয়েছে
StvnW

3
এটি আক্ষরিক অর্থেই আমার মনে জাগে যে আপনি যদি লিঙ্কগুলি অনুসরণ করতে না চান তবে এটিই একমাত্র বুদ্ধিমান সমাধান। ইউনিক্স ওয়ে আমার ফুট।
ড্যানহোহং

34

কোরটিলস প্যাকেজ থেকে পঠন লিঙ্ক ইউটিলিটি ব্যবহার করুন।

MY_PATH=$(readlink -f "$0")

1
বিএসডির কাছে -f পতাকা নেই, এর অর্থ এটি সর্বশেষতম ম্যাকওএস মোজাভে এবং অন্যান্য অনেক সিস্টেমে ব্যর্থ হবে। আপনি বহনযোগ্যতা চাইলে -f ব্যবহার সম্পর্কে ভুলে যান, প্রচুর ওএস-এস প্রভাবিত হয়।
সোমিন ২

1
@sorin। প্রশ্ন ম্যাক সম্পর্কে নয়, এটি লিনাক্স সম্পর্কে।
mattalxndr

14

readlinkপরম পথ অর্জনের জন্য বাশ স্ট্যান্ডার্ড। পাথ বা কোনও পথ উপস্থিত না থাকলে খালি স্ট্রিংগুলি ফিরিয়ে আনার সুবিধাও রয়েছে (পতাকাগুলি দেওয়াতে দেওয়া হয়েছে)।

যে ডিরেক্টরি থাকতে পারে বা নাও থাকতে পারে এমন কোনও ডিরেক্টরিতে পরম পাথ পেতে, তবে কার পিতামাতার অস্তিত্ব রয়েছে, তা ব্যবহার করুন:

abspath=$(readlink -f $path)

যে ডিরেক্টরিতে সমস্ত পিতামাতার সাথে অবশ্যই বিদ্যমান থাকতে হবে তার নিখুঁত পথ পেতে:

abspath=$(readlink -e $path)

প্রদত্ত পাথটিকে আধ্যাত্মিককরণ করতে এবং সিমলিংকগুলির উপস্থিতি ঘটে যদি তা অনুসরণ করে তবে অন্যথায় অনুপস্থিত ডিরেক্টরিগুলি উপেক্ষা করুন এবং যেভাবেই হোক পথটি ফিরিয়ে দিন, এটি হ'ল:

abspath=$(readlink -m $path)

কেবলমাত্র খারাপ দিকটি হ'ল রিডলিঙ্কগুলি লিঙ্কগুলি অনুসরণ করবে। আপনি যদি লিঙ্কগুলি অনুসরণ করতে না চান তবে আপনি এই বিকল্প কনভেনশনটি ব্যবহার করতে পারেন:

abspath=$(cd ${path%/*} && echo $PWD/${path##*/})

এটি $ পাথের ডিরেক্টরি অংশে chdir হবে এবং directory পাথের ফাইল অংশের সাথে বর্তমান ডিরেক্টরিটি প্রিন্ট করবে। এটি chdir ব্যর্থ হলে, আপনি একটি খালি স্ট্রিং এবং স্টাডার উপর একটি ত্রুটি পাবেন।


7
readlinkএটি উপলব্ধ থাকলে একটি ভাল বিকল্প। ওএস এক্স সংস্করণ -eবা -fবিকল্পগুলি সমর্থন করে না । প্রথম তিনটি উদাহরণে, $pathফাইলের মধ্যে স্পেস বা ওয়াইল্ডকার্ডগুলি পরিচালনা করতে আপনার চারপাশে ডাবল-কোট থাকা উচিত । প্যারামিটার সম্প্রসারণের জন্য +1, তবে এটিতে সুরক্ষা দুর্বলতা রয়েছে। যদি pathখালি থাকে তবে এটি cdআপনার হোম ডিরেক্টরিতে চলে যাবে। আপনার ডাবল উক্তি দরকার। abspath=$(cd "${path%/*}" && echo "$PWD/${path##*/}")
টক্সালোট

এটি কেবল একটি উদাহরণ ছিল। আপনি যদি সুরক্ষার দিকে ন্যস্ত হন তবে আপনার আসলে বাশ বা অন্য কোনও শেল বৈকল্পিক ব্যবহার করা উচিত নয়। এছাড়াও, প্ল্যাটফর্মের সামঞ্জস্যের ক্রস করার ক্ষেত্রে বাশের নিজস্ব সমস্যা রয়েছে এবং পাশাপাশি বড় সংস্করণগুলির মধ্যে কার্যকারিতা পরিবর্তনের সমস্যা রয়েছে। ওএসএক্স শেল স্ক্রিপ্টিং সম্পর্কিত প্রাসঙ্গিক বিষয়গুলির সাথে অনেকগুলি প্ল্যাটফর্মগুলির মধ্যে একটি, এটি BSD এর উপর ভিত্তি করে উল্লেখ করা উচিত নয়। যখন আপনাকে সত্যিকার অর্থে একাধিক প্ল্যাটফর্ম হতে হবে, আপনাকে পসিক্স অনুগত হতে হবে, সুতরাং প্যারামিটারের সম্প্রসারণটি উইন্ডো থেকে সত্যই বাইরে যায়। সোলারিস বা এইচপি-ইউএক্স কিছু সময় দেখুন।
ক্রেগ

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

13

পুরানো প্রশ্ন, তবে যদি আপনি শেল স্তরে পুরো পথের নাম নিয়ে কাজ করে থাকেন তবে আরও সহজ উপায় রয়েছে :

   abspath = "$ (সিডি" $ পথ "&&WW)"

সিডি যেমন একটি সাবশেলে ঘটে তা মূল স্ক্রিপ্টকে প্রভাবিত করে না।

আপনার শেলটি অন্তর্নির্মিত কমান্ড -L এবং -P স্বীকার করে মনে করে দুটি ভিন্নতা হ'ল:

   abspath = "$ (সিডি -পি" $ পাথ "&& pwd -P)" # সমাধানিত প্রতিলিপিগুলি সহ ফিজিক্যাল পাথ
   abspath = "$ (সিডি-এল" $ পাথ "&& pwd -L)" # লজিক্যাল পাথ প্রতিলিপি সংরক্ষণ

ব্যক্তিগতভাবে, আমার কোনও কারণেই প্রতীকী লিঙ্কগুলিতে মুগ্ধ না হলে আমার এই বিরল পদ্ধতির খুব কমই প্রয়োজন।

এফওয়াইআই: স্ক্রিপ্টটির বর্তমান ডিরেক্টরিটি পরে পরিবর্তিত হলেও স্ক্রিপ্টের সূচনা ডিরেক্টরি প্রাপ্তির প্রকরণ।

নাম0 = "$ (বেসনাম" $ 0 ")"; স্ক্রিপ্টের #Base নাম
dir0 = "$ (সিডি" $ (dirname "$ 0") "" && pwd) "; নিখরচায় শুরু

সিডি ব্যবহার আপনাকে আশ্বাস দেয় সর্বদা পরম ডিরেক্টরি, এমনকি স্ক্রিপ্টটি ./script.sh এর মতো কমান্ড দ্বারা চালিত হয় যা সিডি / পিডাব্লুডি ছাড়া প্রায়শই কেবল দেয় .. অকার্যকর যদি স্ক্রিপ্ট পরে সিডি না করে থাকে।


8

অ্যাডাম লিস লক্ষ করেছেন realpathযে প্রতিটি বিতরণের সাথে একত্রিত হয় না। যা লজ্জাজনক, কারণ এটি সর্বোত্তম সমাধান। প্রদত্ত উত্স কোডটি দুর্দান্ত, এবং আমি সম্ভবত এটি এখনই ব্যবহার শুরু করব। আমি এখন অবধি যা ব্যবহার করে আসছি তা এখানে কেবল সম্পূর্ণতার জন্য ভাগ করছি:

get_abs_path() {
     local PARENT_DIR=$(dirname "$1")
     cd "$PARENT_DIR"
     local ABS_PATH="$(pwd)"/"$(basename "$1")"
     cd - >/dev/null
     echo "$ABS_PATH"
} 

আপনি সমাধান symlinks তা চান, শুধু প্রতিস্থাপন pwdসঙ্গে pwd -P


এই কেসটির pwd -Pবিকল্প সহ একটি গ্যাচা ... $(basename "$1")অন্য ডিরেক্টরিতে কোনও ফাইলে একটি সিএমলিংক হলে কী হবে তা বিবেচনা করুন । pwd -Pশুধুমাত্র পথের ডিরেক্টরির অংশ symlinks সমাধান করা, কিন্তু না basename অংশ।
toxalot

7

আমার সাম্প্রতিক সমাধানটি ছিল:

pushd foo/bar/..
dir=`pwd`
popd

টিম হুইটকম্বের উত্তরের ভিত্তিতে।


যুক্তিটি ডিরেক্টরি না হলে আমি এটি ব্যর্থ হয়েছি সন্দেহ। ধরুন আমি জানতে চাই / usr / bin / java কোথায় যায়?
এডওয়ার্ড ফালক

1
যদি আপনি জানেন যে এটি কোনও ফাইল, আপনি pushd $(dirname /usr/bin/java)চেষ্টা করে দেখতে পারেন।
স্কচমুনক

5

ঠিক কোনও উত্তর নয় তবে সম্ভবত একটি ফলো-আপ প্রশ্ন (মূল প্রশ্নটি সুস্পষ্ট ছিল না):

readlinkঠিক আছে যদি আপনি প্রকৃতপক্ষে অনুসরণ করতে চান follow কিন্তু সেখানে নিছক স্বাভাবিক একটি ব্যবহার ক্ষেত্রে দেখা যায় ./এবং ../এবং //সিকোয়েন্স, যা বিশুদ্ধরূপে চিহ্নগুলি সিন্টেক্সের কাজ করা যেতে পারে, ছাড়া symlinks canonicalizing। readlinkএটির জন্য ভাল নয় এবং হয়ও না realpath

for f in $paths; do (cd $f; pwd); done

বিদ্যমান পাথের জন্য কাজ করে তবে অন্যের জন্য বিরতি দেয়।

একটি sedস্ক্রিপ্ট একটি ভাল বাজি হবে বলে মনে হচ্ছে না, ছাড়া আপনি iteratively এই সিকোয়েন্স প্রতিস্থাপন করতে পারবেন না ( /foo/bar/baz/../..-> /foo/bar/..-> /foo) পার্ল, যা সব সিস্টেমে অনুমান করা, অথবা কিছু কুশ্রী লুপ ব্যবহার আউটপুট তুলনা নিরাপদ নয় ভালো কিছু ব্যবহার না করেই sedকরতে এর ইনপুট

এফডাব্লুআইডাব্লু, জাভা (জেডিকে 6+) ব্যবহার করে একটি ওয়ান-লাইনার:

jrunscript -e 'for (var i = 0; i < arguments.length; i++) {println(new java.io.File(new java.io.File(arguments[i]).toURI().normalize()))}' $paths

realpathএকটি আছে -sপ্রতি সিম্বলিক লিঙ্ক এবং একমাত্র সমাধান রেফারেন্স সমাধান না বিকল্প /./, /../এবং অতিরিক্ত অপসারণ /অক্ষর। -mবিকল্পটির সাথে একত্রিত হয়ে , realpathকেবলমাত্র ফাইলের নামে চালিত হয় এবং কোনও আসল ফাইল স্পর্শ করে না। এটি নিখুঁত সমাধান মত শোনাচ্ছে । কিন্তু হায়, realpathএখনও অনেক সিস্টেমে অনুপস্থিত।
টেক্সালট

..সিমলিঙ্কগুলি জড়িত থাকাকালীন উপাদানগুলি সরানো সিনথেটিকভাবে করা যায় না। /one/two/../threeহিসাবে একই নয় /one/threeযদি twoএকটি সিমবলিক লিঙ্ক হয় /foo/bar
jrw32982

@ jrw32982 হ্যাঁ আমি আমার প্রতিক্রিয়াতে যেমন বলেছি এটি যখন ব্যবহারের ক্ষেত্রে হয় তখন যখন সিমলিংক ক্যানোনিকালাইজেশন না চাওয়া বা প্রয়োজন হয় না
জেসি গ্লিক

@ জেসিগ্লিক করুন আপনি কেবল সিমলিংকগুলি ক্যানোনিকালাইজ করতে চান কিনা তা কেবল এটির একটি ঘটনা নয়। আপনার অ্যালগরিদম আসলে ভুল উত্তর উত্পাদন করে। আপনার উত্তরটি সঠিক হওয়ার জন্য, আপনাকে একটি অগ্রাধিকার জানতে হবে যে এতে কোনও প্রতিলিঙ্ক জড়িত ছিল না (বা তারা কেবল একটি নির্দিষ্ট ফর্মের ছিল)। আপনার উত্তরটি বলে যে আপনি এগুলিকে আধ্যাত্মিক করতে চান না, এমন নয় যে পথে কোনও সংযুক্তি নেই।
jrw32982 মনিকাকে

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

5

আমি পার্টিতে দেরি করেছি, তবে এই সমাধানগুলি আমি এই জাতীয় থ্রেডগুলি পড়ার পরে তৈরি করেছি:

resolve_dir() {
        (builtin cd `dirname "${1/#~/$HOME}"`'/'`basename "${1/#~/$HOME}"` 2>/dev/null; if [ $? -eq 0 ]; then pwd; fi)
}

এটি $ 1 এর নিখুঁত পথটি সমাধান করবে, nice দিয়ে দুর্দান্ত খেলবে, সিমলিংকগুলি যেখানে রয়েছে সেদিকে রাখবে এবং এটি আপনার ডিরেক্টরি স্ট্যাকের সাথে বিঘ্নিত হবে না। এটি পুরোপথ ফেরত দেয় বা অস্তিত্ব না থাকলে কিছুই না। এটি directory 1 কে একটি ডিরেক্টরি হতে আশা করে এবং সম্ভবত এটি ব্যর্থ হলে এটি ব্যর্থ হবে, তবে এটি নিজেকে করার একটি সহজ চেক।


4

কথাবার্তা, এবং কিছুটা দেরি করে দেওয়া উত্তর। আমি পুরানো RHEL4 / 5 এ আটকে থাকায় আমার একটি লিখতে হবে। আমি নিখুঁত এবং আপেক্ষিক লিঙ্কগুলি পরিচালনা করি এবং //, /./ এবং সামুদির /.. / এন্ট্রিগুলি সহজ করে।

test -x /usr/bin/readlink || readlink () {
        echo $(/bin/ls -l $1 | /bin/cut -d'>' -f 2)
    }


test -x /usr/bin/realpath || realpath () {
    local PATH=/bin:/usr/bin
    local inputpath=$1
    local changemade=1
    while [ $changemade -ne 0 ]
    do
        changemade=0
        local realpath=""
        local token=
        for token in ${inputpath//\// }
        do 
            case $token in
            ""|".") # noop
                ;;
            "..") # up one directory
                changemade=1
                realpath=$(dirname $realpath)
                ;;
            *)
                if [ -h $realpath/$token ] 
                then
                    changemade=1
                    target=`readlink $realpath/$token`
                    if [ "${target:0:1}" = '/' ]
                    then
                        realpath=$target
                    else
                        realpath="$realpath/$target"
                    fi
                else
                    realpath="$realpath/$token"
                fi
                ;;
            esac
        done
        inputpath=$realpath
    done
    echo $realpath
}

mkdir -p /tmp/bar
(cd /tmp ; ln -s /tmp/bar foo; ln -s ../.././usr /tmp/bar/link2usr)
echo `realpath /tmp/foo`

3

আমাদের নতুন বাশ লাইব্রেরি পণ্য রিয়েলপথ-লিব চেষ্টা করুন যা আমরা গিটহাবের উপর বিনামূল্যে এবং নিরবিচ্ছিন্ন ব্যবহারের জন্য রেখেছি । এটি পুঙ্খানুপুঙ্খভাবে নথিভুক্ত এবং একটি দুর্দান্ত শেখার সরঞ্জাম তৈরি করে।

এটি স্থানীয়, আপেক্ষিক এবং পরম পাথ সমাধান করে এবং বাশ 4+ ব্যতীত কোনও নির্ভরতা নেই; সুতরাং এটি প্রায় কোথাও কাজ করা উচিত। এটি বিনামূল্যে, পরিষ্কার, সরল এবং শিক্ষণীয় tive

আপনি করতে পারেন:

get_realpath <absolute|relative|symlink|local file path>

এই ফাংশনটি গ্রন্থাগারের মূল বিষয়:

function get_realpath() {

if [[ -f "$1" ]]
then 
    # file *must* exist
    if cd "$(echo "${1%/*}")" &>/dev/null
    then 
        # file *may* not be local
        # exception is ./file.ext
        # try 'cd .; cd -;' *works!*
        local tmppwd="$PWD"
        cd - &>/dev/null
    else 
        # file *must* be local
        local tmppwd="$PWD"
    fi
else 
    # file *cannot* exist
    return 1 # failure
fi

# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success

}

এটিতে get_dirname, get_filename, get_ স্টেমনাম এবং বৈধতা প্রদানের ফাংশন রয়েছে। প্ল্যাটফর্ম জুড়ে এটি চেষ্টা করুন এবং এটি উন্নত করতে সহায়তা করুন।


2

সমস্যাটি realpathহ'ল এটি BSD এ উপলব্ধ নয় (বা সেই বিষয়ে OSX)। এখানে লিনাক্স জার্নাল থেকে বরং পুরানো (২০০৯) নিবন্ধ থেকে সরানো একটি সাধারণ রেসিপি দেওয়া হয়েছে , এটি যথেষ্ট বহনযোগ্য:

function normpath() {
  # Remove all /./ sequences.
  local path=${1//\/.\//\/}

  # Remove dir/.. sequences.
  while [[ $path =~ ([^/][^/]*/\.\./) ]]; do
    path=${path/${BASH_REMATCH[0]}/}
  done
  echo $path
}

লক্ষ্য করুন এই বৈকল্পিক এছাড়াও করেন না অস্তিত্ব পথ প্রয়োজন।


এটি তবে সিমলিংকগুলি সমাধান করে না। রিয়েলপথ মূল থেকে শুরু হওয়া পাথগুলি প্রক্রিয়া করে এবং অগ্রগতির সাথে সাথে প্রতীকগুলি অনুসরণ করে। এই সমস্ত কাজ পিতামাতার রেফারেন্স হ'ল।
মার্টিজন পিটারস

2

@ আন্দ্রে এর উত্তরের ভিত্তিতে আমার কিছুটা উন্নত সংস্করণ থাকতে পারে, যদি কেউ লুপ-মুক্ত, সম্পূর্ণ স্ট্রিং-ম্যানিপুলেশন ভিত্তিক সমাধানের পরে থাকে। এটি তাদের জন্যও কার্যকর যারা কোনও প্রতিলিঙ্ককে অবহেলা করতে চান না, যা ব্যবহারের realpathবা খারাপ দিক readlink -f

এটি বাশ সংস্করণে ৩.২.২৫ এবং উচ্চতর ক্ষেত্রে কাজ করে।

shopt -s extglob

normalise_path() {
    local path="$1"
    # get rid of /../ example: /one/../two to /two
    path="${path//\/*([!\/])\/\.\./}"
    # get rid of /./ and //* example: /one/.///two to /one/two
    path="${path//@(\/\.\/|\/+(\/))//}"
    # remove the last '/.'
    echo "${path%%/.}"
}

$ normalise_path /home/codemedic/../codemedic////.config
/home/codemedic/.config

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

দুঃখিত @ricovox; আমি এখন সেগুলি আপডেট করেছি। আপনার কাছে থাকা বাশের সঠিক সংস্করণটি জানতে আগ্রহী। উপরের সূত্রটি (আপডেট করা হয়েছে) সেন্টোস ৫.৮ এ কাজ করে যা ব্যাশ ৩.২.২৫ নিয়ে আসে
εδιϲমাচ

বিভ্রান্তির জন্য দুঃখিত. এই কোডটি ডিআইডি আমার ম্যাক ওএসএক্স বাশনের সংস্করণে (3.2.57) কাজ করে যখন আমি এক্সট্লোব চালু করেছিলাম। ব্যাশ সংস্করণ সম্পর্কে আমার নোটটি আরও সাধারণ ছিল (যা প্রকৃতপক্ষে ব্যাশের রিজেক্স সম্পর্কিত আরও একটি উত্তরে আরও প্রযোজ্য)।
drwatsoncode

2
আমি আপনার উত্তর প্রশংসা করি যদিও। আমি এটিকে নিজের জন্য বেস হিসাবে ব্যবহার করেছি। ঘটনাক্রমে আমি বেশিরভাগ ক্ষেত্রে লক্ষ্য করেছি যেখানে আপনার ব্যর্থতা রয়েছে: (1) আপেক্ষিক পাথ hello/../world(2) ফাইলনেটে বিন্দু /hello/..world(3) ডাবল-স্ল্যাশের পরে বিন্দু /hello//../world(4) ডাবল-স্ল্যাশের আগে বা পরে বিন্দু /hello//./worldবা /hello/.//world (5) বর্তমানের পরে পিতা বা মাতা: /hello/./../world/ (6) পিতা বা মাতা পিতামাতার পরে: /hello/../../worldইত্যাদি - এর মধ্যে কয়েকটি লুপ ব্যবহার করে সংশোধন করা যেতে পারে যতক্ষণ না পথ পরিবর্তন বন্ধ হয়। (এছাড়াও সরান dir/../, কিন্তু শেষ থেকে /dir/..অপসারণ dir/..করুন।)
drwatsoncode

0

লাভবার্গের দুর্দান্ত পাইথনের স্নিপেটের ভিত্তিতে আমি এটি লিখেছি:

#!/bin/sh

# Version of readlink that follows links to the end; good for Mac OS X

for file in "$@"; do
  while [ -h "$file" ]; do
    l=`readlink $file`
    case "$l" in
      /*) file="$l";;
      *) file=`dirname "$file"`/"$l"
    esac
  done
  #echo $file
  python -c "import os,sys; print os.path.abspath(sys.argv[1])" "$file"
done

0
FILEPATH="file.txt"
echo $(realpath $(dirname $FILEPATH))/$(basename $FILEPATH)

ফাইলটি বিদ্যমান না থাকলেও এটি কাজ করে। এটির জন্য ফাইলটি উপস্থিত ডিরেক্টরি থাকতে হবে।


আপনি যদি না ব্যবহার করেন তবে জিএনইউ রিয়েলপথের অস্তিত্বের পথে শেষ উপাদানটির প্রয়োজন নেইrealpath -e
মার্টিজন পিটার

0

আমার একটি সমাধান দরকার যা তিনটিই করবে:

  • একটি স্টক ম্যাক কাজ। realpathএবং readlink -faddons হয়
  • প্রতিলিঙ্কগুলি সমাধান করুন olve
  • পরিচালনা করতে ত্রুটি আছে

উত্তরের কোনওটিতেই # 1 এবং # 2 উভয়ই ছিল না। অন্যদের আরও য্যাক শেভ করতে বাঁচাতে আমি # 3 যুক্ত করেছি।

#!/bin/bash

P="${1?Specify a file path}"

[ -e "$P" ] || { echo "File does not exist: $P"; exit 1; }

while [ -h "$P" ] ; do
    ls="$(ls -ld "$P")"
    link="$(expr "$ls" : '.*-> \(.*\)$')"
    expr "$link" : '/.*' > /dev/null &&
        P="$link" ||
        P="$(dirname "$P")/$link"
done
echo "$(cd "$(dirname "$P")"; pwd)/$(basename "$P")"

উদ্ধৃতি সম্পূর্ণরূপে ব্যায়াম করার জন্য এখানে কয়েকটি মোচড় জায়গা দিয়ে একটি সংক্ষিপ্ত পরীক্ষার কেস দেওয়া হয়েছে

mkdir -p "/tmp/test/ first path "
mkdir -p "/tmp/test/ second path "
echo "hello" > "/tmp/test/ first path / red .txt "
ln -s "/tmp/test/ first path / red .txt " "/tmp/test/ second path / green .txt "

cd  "/tmp/test/ second path "
fullpath " green .txt "
cat " green .txt "

0

আমি জানি এটি একটি প্রাচীন প্রশ্ন। আমি এখনও একটি বিকল্প প্রস্তাব করছি। সম্প্রতি আমি একই ইস্যুটির সাথে দেখা করেছি এবং এটি করার জন্য কোনও বিদ্যমান এবং বহনযোগ্য কমান্ড পাইনি। সুতরাং আমি নিম্নলিখিত শেল স্ক্রিপ্ট লিখেছিলাম যাতে একটি ফাংশন অন্তর্ভুক্ত যা কৌশলটি করতে পারে।

#! /bin/sh                                                                                                                                                

function normalize {
  local rc=0
  local ret

  if [ $# -gt 0 ] ; then
    # invalid
    if [ "x`echo $1 | grep -E '^/\.\.'`" != "x" ] ; then
      echo $1
      return -1
    fi

    # convert to absolute path
    if [ "x`echo $1 | grep -E '^\/'`" == "x" ] ; then
      normalize "`pwd`/$1"
      return $?
    fi

    ret=`echo $1 | sed 's;/\.\($\|/\);/;g' | sed 's;/[^/]*[^/.]\+[^/]*/\.\.\($\|/\);/;g'`
  else
    read line
    normalize "$line"
    return $?
  fi

  if [ "x`echo $ret | grep -E '/\.\.?(/|$)'`" != "x" ] ; then
    ret=`normalize "$ret"`
    rc=$?
  fi

  echo "$ret"
  return $rc
}

https://gist.github.com/bestofsong/8830bdf3e5eb9461d27313c3c282868c


0

আমি সর্বোচ্চ সম্ভাব্য পারফরম্যান্সের (মজাদার জন্য) ফোকাস দিয়ে এটিকে পরিচালনা করার জন্য একটি অন্তর্নির্মিত ফাংশন করেছি। এটি সিমলিংকগুলি সমাধান করে না, তাই এটি মূলত একই realpath -sm

## A bash-only mimic of `realpath -sm`. 
## Give it path[s] as argument[s] and it will convert them to clean absolute paths
abspath () { 
  ${*+false} && { >&2 echo $FUNCNAME: missing operand; return 1; };
  local c s p IFS='/';  ## path chunk, absolute path, input path, IFS for splitting paths into chunks
  local -i r=0;         ## return value

  for p in "$@"; do
    case "$p" in        ## Check for leading backslashes, identify relative/absolute path
    '') ((r|=1)); continue;;
    //[!/]*)  >&2 echo "paths =~ ^//[^/]* are impl-defined; not my problem"; ((r|=2)); continue;;
    /*) ;;
    *)  p="$PWD/$p";;   ## Prepend the current directory to form an absolute path
    esac

    s='';
    for c in $p; do     ## Let IFS split the path at '/'s
      case $c in        ### NOTE: IFS is '/'; so no quotes needed here
      ''|.) ;;          ## Skip duplicate '/'s and '/./'s
      ..) s="${s%/*}";; ## Trim the previous addition to the absolute path string
      *)  s+=/$c;;      ### NOTE: No quotes here intentionally. They make no difference, it seems
      esac;
    done;

    echo "${s:-/}";     ## If xpg_echo is set, use `echo -E` or `printf $'%s\n'` instead
  done
  return $r;
}

দ্রষ্টব্য: এই ফাংশনটি শুরু হওয়া পাথগুলি পরিচালনা করে না //, কারণ কোনও পথের শুরুতে ঠিক দুটি ডাবল স্ল্যাশ বাস্তবায়ন-সংজ্ঞায়িত আচরণ। তবে এটি পরিচালনা করে /, ///এবং ঠিক ঠিক।

এই ফাংশনটি সমস্ত প্রান্তের কেসগুলি সঠিকভাবে পরিচালনা করবে বলে মনে হয়, তবে এখনও সেখানে কিছু থাকতে পারে যা আমি মোকাবেলা করি নি।

পারফরম্যান্স নোট: যখন হাজার হাজার আর্গুমেন্টের সাথে ডাকা হয় তখন abspathপ্রায় 10x কম ধীর হয় realpath -sm; যখন একক যুক্তি দিয়ে ডাকা হয়, তখন আমার মেশিনের abspathচেয়ে 110x দ্রুত চলে যায় realpath -sm, বেশিরভাগ সময় প্রতিবার নতুন প্রোগ্রাম চালানোর প্রয়োজন না হওয়ার কারণে।


-1

আমি আজ আবিষ্কার করেছি যে আপনি statপাথগুলি সমাধান করতে কমান্ডটি ব্যবহার করতে পারেন ।

সুতরাং "~ / ডকুমেন্টস" এর মতো ডিরেক্টরিতে:

আপনি এটি চালাতে পারেন:

stat -f %N ~/Documents

সম্পূর্ণ পথ পেতে:

/Users/me/Documents

সিমলিংকের জন্য, আপনি% Y ফর্ম্যাট বিকল্পটি ব্যবহার করতে পারেন:

stat -f %Y example_symlink

যা এর মতো ফলাফল ফিরে আসতে পারে:

/usr/local/sbin/example_symlink

ফর্ম্যাট করার বিকল্পগুলি * এনআইএক্স এর অন্যান্য সংস্করণে ভিন্ন হতে পারে তবে এটি ওএসএক্সে আমার জন্য কাজ করেছে।


1
stat -f %N ~/Documentsলাইন একটি লাল হেরিং ... আপনার শেল প্রতিস্থাপন করা হয় ~/Documentsসঙ্গে /Users/me/Documents, এবং statমাত্র ধারণকৃত যুক্তি মুদ্রণ করা হয়।
Danwyand

-4

ব্যবহার করে একটি সহজ সমাধান node.js:

#!/usr/bin/env node
process.stdout.write(require('path').resolve(process.argv[2]));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.