দীর্ঘ পথে প্রথম অনুপস্থিত ডিরেক্টরিটি কীভাবে খুঁজে পাব?


14

ভাবুন আমার এমন একটি পথ রয়েছে যা বিদ্যমান নেই:

$ ls /foo/bar/baz/hello/world
ls: cannot access /foo/bar/baz/hello/world: No such file or directory

তবে আসুন বলুন /foo/bar যে বিদ্যমান আছে। আমার জন্য bazকি এই উপায়টির ব্রেকিং পয়েন্টটি নির্ধারণ করার জন্য দ্রুত উপায় আছে ?

আমি ব্যাশ ব্যবহার করছি


access(2)খুব দানাদার নয়, তাই সমাধানটিতে সাধারণত প্রতিটি পথের উপাদানগুলি পুনরাবৃত্তি করতে এবং পরীক্ষার জন্য কিছু লেখা থাকে ...
ফ্রি

উত্তর:


5

আপনার মত একটি ক্যানোনিকাল পথ দেওয়া, এটি কাজ করবে:

set -f --; IFS=/
for p in $pathname
do    [ -e "$*/$p" ] || break
      set -- "$@" "$p"
done; printf %s\\n "$*"

এটি সর্বশেষে বিদ্যমান / অ্যাক্সেসযোগ্য উপাদানটির সর্বশেষ অংশের মাধ্যমে মুদ্রণ $pathnameকরে এবং সেগুলির প্রত্যেককে পৃথকভাবে আর্গের অ্যারেতে রাখে। প্রথম অস্তিত্বযুক্ত উপাদান মুদ্রিত করা হয়নি, তবে এটি সংরক্ষণ করা হয়েছে $p

আপনি এর বিপরীতে যেতে পারেন:

until cd -- "$path" && cd -
do    case   $path  in
      (*[!/]/*)
              path="${path%/*}"
;;    (*)   ! break
      esac
done  2>/dev/null   && cd -

এটি হয় যথাযথভাবে ফিরে আসবে বা $pathপ্রয়োজন অনুসারে নামবে । /এটিতে পরিবর্তনের চেষ্টা করতে অস্বীকৃতি জানায় , তবে সফল হলে এটি আপনার বর্তমান ওয়ার্কিং ডিরেক্টরি এবং ডিরেক্টরিটি যেখানে স্টাডাউটে পরিবর্তিত হবে উভয়ই মুদ্রণ করবে। আপনার বর্তমান এছাড়াও করা $PWDহবে $OLDPWD


স্পষ্টত: for p in $pathname"শব্দ বিভাজন" এবং "পাঠের নাম সম্প্রসারণ" সাপেক্ষে।

1
@ বাইনারিজেব্রা - হ্যাঁ, এটি বিভক্ত $IFS। ঠিক এভাবেই এটি কাজ করে। এটি $pathnameপথের নাম প্রসারণ সাপেক্ষে নয়, এখানে বলা চলকটি বিভাজক হিসাবে পথের উপাদানগুলির অ্যারেতে প্রসারিত হয় $IFS
মাইকজার্ভ

আপনি Var এ "পথনাম সম্প্রসারণ" এড়ানো হয় $pathname ব্যবহার করে set -f"যা তার ডিফল্ট মান ফিরে করা হয় না।

@ বাইনারিজেব্রা - আমি কিছু এড়ানো হচ্ছে না। আমি দৃ rob়ভাবে এই কাজ করার জন্য আমার প্রয়োজনীয় পরিবেশটি উল্লেখ করছি। এখানেই শেষ. না - এটি তার ডিফল্ট মানটিতে ফিরে আসে না এবং এটি নিজেই জিজ্ঞাসকের কম্পিউটারে ইনস্টল করবে না বা আমাকে প্রাতঃরাশ তৈরি করবে।
মাইকসার্ভ

1
@ বাইনারিজেব্রা - তবে, যদি কোনও ভাল প্রোগ্রামার হওয়া উচিত, তবে আপনি প্রায়শই আপনার মৃত্যুদন্ডের পরিবেশকে অপ্রয়োজনীয়ভাবে প্রভাবিত / পুনরুদ্ধার করার জন্য নিজেকে চিন্তিত করতে দেখেন, আপনি আগ্রহী হতে পারেন ns, যদি এখানে ব্যবহৃত হয়, তবে এই আলোচনার বিষয়টিকে রেন্ডার করবে।
মাইকসার্ভ

12

আমার প্রিয় ইউটিলিটিগুলির একটি হ'ল এর nameiঅংশ util-linuxএবং তাই সাধারণত লিনাক্সে উপস্থিত:

$ namei /usr/share/foo/bar
f: /usr/share/foo/bar
 d /
 d usr
 d share
   foo - No such file or directory

তবে এর আউটপুট খুব বিশ্লেষণযোগ্য নয়। সুতরাং, যদি আপনি কেবল কোনও কিছু অনুপস্থিত nameiদেখিয়ে দিতে চান তবে দরকারী হতে পারে।

কোনও পাথ অ্যাক্সেস করার ক্ষেত্রে সাধারণ সমস্যা সমাধানের জন্য এটি দরকারী, যেহেতু আপনি এটি কোনও উপাদান কোনও লিঙ্ক বা মাউন্ট পয়েন্ট কিনা তা পাশাপাশি এটির অনুমতিও তা নির্ধারণ করতে পারেন:

$ ln -sf /usr/foo/bar /tmp/
$ namei -lx /tmp/bar
f: /tmp/bar
Drwxr-xr-x root    root    /
Drwxrwxrwt root    root    tmp
lrwxrwxrwx muru    muru    bar -> /usr/foo/bar
Drwxr-xr-x root    root      /
drwxr-xr-x root    root      usr
                             foo - No such file or directory

মূলধন Dএকটি মাউন্ট পয়েন্ট নির্দেশ করে।


@ স্টাফেনচাজেলাস আমি আশা করি সমতুল্য অন্যান্য সিস্টেমে উপস্থিত থাকতে পারে। বিএসডিদের জন্য কিছুই নেই?
মুরু

nameiআমার পক্ষে ততক্ষণ কাজ করে যতক্ষণ এটি খাদ্য হিসাবে এটি উপস্থিত একটি পথ, তবে যখন আমি এটি দিয়ে যাই যা আমি পাই না namei: failed to stat: /usr/share/foo/bar: No such file or directory
কুজ্জুরু

@ কিউজুরো কোন নামি সংস্করণ?
মারু

আমার নামির সংস্করণটি তার সাহায্যে বা এর ম্যান পৃষ্ঠায় কোনও সংস্করণ দেয় না এবং কোনও পতাকা সরবরাহকারী সংস্করণ তথ্য সমর্থন করে না। আমি এটি নির্ধারণ করতে সক্ষম হয়েছি যে এটি প্যাকেজ লিনাক্স-ইউটিস ২.১-1-১ ইউবুন্টু ৫ থেকে এসেছে তবে এটি নামির সংস্করণের জন্য কী বোঝায় তা বুঝতে পারি না।
কুজ্জুরু

@kuzzooroo যেহেতু উবুন্টু 12.04 এরও 2.20.1 রয়েছে , আপনার অবশ্যই উবুন্টুর খুব পুরানো সংস্করণে থাকতে হবে। 10.04?
মুড়ু

1

এরকম কিছু (এম্বেড শূন্যস্থান সহ পথনামগুলির অ্যাকাউন্টিং):

#!/bin/sh
explain() {
    if [ -d "$1" ]
    then
        printf "\t%s: is a directory\n" "$1"
    elif [ -e "$1" ]
    then
        printf "\t%s: is not a directory\n" "$1"
    else
        printf "\t%s: does not exist\n" "$1"
    fi
}

for item in "$@"
do
    last=
    test="$item"
    printf "testing: '%s'\n" "$item"
    while [ ! -d "$test" ]
    do
        last="$test"
        test=$(dirname "$test")
        [ -z "$test" ] && break
    done
    if [ -n "$last" ]
    then
        explain "$test"
        explain "$last"
    else
        printf "\t%s: ok\n" "$item"
    fi
done

এটি ধরে নিয়েছে যে আর্গুমেন্টগুলি বোঝানো হচ্ছে ডিরেক্টরিগুলি (বা ডিরেক্টরিতে প্রতিলিঙ্ক)।
স্টাফেন চেজেলাস

1
যদি আপনি কেবল cd not_a_directoryআপনার শেলটি স্ট্যাডারকে লিখবেন ঠিক তেমন কিছু cd:cd:6: no such file or directory: not_a_directory। প্রকৃতপক্ষে, ব্যবহারকারীর শেলটি এমন ফর্ম্যাটে করবে যাতে ব্যবহারকারী সম্ভবত ইতিমধ্যে খুব পরিচিত। তার প্রায় সবসময় শুধু উভয় সহজ এবং যাহাই হউক না কেন শেষ ভালো করার কি কাপড় এবং শেল হ্যান্ডেল প্রয়োজনীয় হিসাবে প্রতিবেদন করা যাক। এই ধরণের দর্শনের ক্ষেত্রে মানগুলি ফেরত দেওয়ার জন্য এবং এর প্রচার / সংরক্ষণের জন্য খুব কঠোর মনোযোগ প্রয়োজন।
মাইকজার্ভ

1

বাশের জন্য বিকল্প বিকল্প, পথ ধরে নিলে এক পরম পথ (দিয়ে শুরু হয় /):

#!/bin/bash

pathname="$1"

IFS='/' read -r -a p <<<"${pathname#/}"

pa=""    max="${#p[@]}"    i=0
while (( i<"$max" )); do
      pa="$pa/${p[i++]}"
      if     [[ ! -e $pa ]]; then
             printf 'failed at: \t"%s"\t"%s"\n' "${pa##*/}" "${pa}"
             break
      fi
done

$ ./script "/foo/ba r/baz/hello/world"
failed at:      "hello"        "/foo/ba r/baz/hello"

এটি আমার পক্ষে কাজ করেছে। আমি পথ স্ট্রিং গত বৈধ পথ প্রয়োজন তাই আমি সংরক্ষিত paযেমন pa_prevযখন লুপ প্রথম লাইন (আগেই বৃদ্ধি পায়) হিসেবে। "Pa" এর জন্য পরীক্ষাটি যখন ব্যর্থ হয়, pa_prevতখন প্রদত্ত পথে সর্বশেষ বিদ্যমান ডিরেক্টরি থাকে।
ভিল

0
(( dirct=$(echo ${dir}|tr "/" " "|wc -w)+1 ))
i=2
while [ ${i} -le ${dirct} ]
do
  sdir=$(echo ${dir}|cut -d/ -f1,${i})
  if [ ! -d ${sdir} ]
  then
    echo "Path is broken at ${sdir}"
  fi
  (( i++ ))
done

এটি সহজ নয় তবে আপনি যদি এটি ঘন ঘন ব্যবহার করতে যান তবে আপনি এটি কোনও স্ক্রিপ্টে রাখতে পারেন, এটি কার্যকর করতে পারেন এবং এটি আপনার পথে কোথাও আটকে রাখতে পারেন।

ক্যাভেট এমপোটার: যদি কোনও ডিরেক্টরিতে আপনার ডিরেক্টরিতে নামের একটি spaceঅক্ষর থাকে তবে এটি কাজ করবে না।


এই বাশ কোড? আমাকে ap ir dir in এ পরিবর্তন করতে হবে ফাঁকা হয়ে আসছে তাই আমি $ 1 এ অদলবদল করেছিলাম, তবে এখন sdir আমার কাছে ফাঁকা আসছে।
কুজুরু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.