साधारण सिनेमाहाल कमांड के साथ पूर्ण सिमिलिंक को सापेक्ष सिम्लिंक में परिवर्तित करें


29

मैं एक पथ के अंदर एक पूरी उप फाइल सिस्टम है /home/user/systemनिर्देशिकाओं के साथ मानक Linux संरचना शामिल /bin, /home, /root, /usr, /var, /etc, ...

इस उप-फाइलसिस्टम में प्रतीकात्मक लिंक होते हैं, या तो सापेक्ष या निरपेक्ष। रिश्तेदार सिम्बलिंक्स ठीक हैं, वे उप-फाइलसिस्टम के तहत रहते हैं /home/user/system। लेकिन पूर्ण सहानुभूति समस्याग्रस्त हैं, क्योंकि वे उप-फाइलसिस्टम के बाहर एक लक्ष्य की ओर इशारा करते हैं।

एक उदाहरण के रूप में हम एक पूर्ण सहानुभूति मानते हैं जो निम्न प्रकार है (उप-फाइलसिस्टम के अंदर देखा गया है):

/usr/file1 -> /usr/lib/file1

समग्र फाइल सिस्टम में हम एक पर लिंक है /home/user/system/usr/file1कि अब बात एक फाइल करने के लिए /usr/lib/file1उप फाइल सिस्टम के बाहर एक फ़ाइल के बजाय /home/user/system/usr/lib/file1 अंदर उप फाइल सिस्टम।

मैं एक साधारण स्क्रिप्ट, अधिमानतः एक एकल कमांड लाइन (rsync, chroot, find, ...) चाहूंगा जो हर पूर्ण सहानुभूति को एक रिश्तेदार को परिवर्तित कर दे।

दिए गए उदाहरण में, वह सापेक्ष लिंक बन जाएगा

/usr/file1 -> ../usr/lib/file1

4
इस क्यू को हल करने के प्रयास में रुचि रखने वालों के लिए, यहाँ SO के प्रयास से एक 250k उपयोगकर्ता दोहराएगा: stackoverflow.com/questions/2564634/… । उस धागे में कई संभावित समाधान हैं, लेकिन प्रत्येक के पास विशिष्ट परिस्थितियां हैं जो यह और अन्य लोगों के साथ व्यवहार करता है जो यह नहीं करता है।
स्लम

जवाबों:


20

मार्क लॉर्ड द्वारा symlinksउपयोगिता के साथ (कई वितरणों द्वारा प्रस्तुत; यदि आपके पास यह नहीं है, तो इसे स्रोत से बनाएं ):

chroot /home/user/system symlinks -cr .

वैकल्पिक रूप से, उन सिस्टमों पर, जिनके पास readlinkकमांड और -lnameविधेय है find(चेतावनी: बिना कोड):

cd /home/user/system &&
find . -lname '/*' -exec ksh -c '
  for link; do
    target=$(readlink "$link")
    link=${link#./}
    root=${link//+([!\/])/..}; root=${root#/}; root=${root%..}
    rm "$link"
    ln -s "$root${target#/}" "$link"
  done
' _ {} +

यह एक अच्छा समाधान होगा! हालांकि, खोज _ {} +के अंत में अभिव्यक्ति का क्या मतलब है? इसके अलावा, मुझे एक त्रुटि मिलती है find: paths must precede expression: kshजो समझ में नहीं आती है (जैसा कि पथ ksh अभिव्यक्ति को आगे बढ़ाता है)।
एलेक्स

@Alex _है $0खोल टुकड़ा के लिए, और {} +तर्कों की सूची जो बन ने ले ली है $1, $2आदि, जो for link; do …(यह का पर्याय बन गया है से अधिक लूप for link in "$@"; do …)। findटाइपो के कारण त्रुटि आई है (मैं किसी तरह तर्क के चारों ओर सिंगल कोट्स के बजाय बैकक्वाट्स टाइप करने में कामयाब रहा -lname)।
गिल्स एसओ- बुराई को रोकना '

अब स्क्रिप्ट चलती है, लेकिन उम्मीद के मुताबिक नहीं। शायद मैं पर्याप्त सटीक नहीं था, मैंने सवाल अपडेट किया है।
एलेक्स

@ क्या समस्या है? मुझे लगता है कि सिद्धांत ध्वनि है, लेकिन मैंने कुछ कोडिंग गलतियां की हैं। क्या आपने कोशिश की symlinks? यह आपकी समस्या को हल करेगा - यह मूल रूप से इसके लिए डिज़ाइन किया गया था (इस झुंझलाहट के साथ कि आपको इसे चलाया जाना है ( नकली को चाल करना चाहिए)।
गिल्स एसओ- बुराई को रोकना '10

1
मैं कुछ अतिरिक्त स्थापित करने की आवश्यकता के बिना, बॉक्स से बाहर काम करने वाले समाधान का दृढ़ता से सामना करता हूं।
एलेक्स

4

शुद्ध बैश और कोरुटिल्स, ../पथ में अनावश्यक एस के बिना रिश्तेदार के लिए सिम्बलिंक्स को बदलता है:

find . -type l | while read l; do
    target="$(realpath "$l")"
    ln -fs "$(realpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target")" "$l"
done

तुम बदल सकते हो:

  • find .find /path/to/directoryसहानुभूति को उस निर्देशिका में परिवर्तित करने के लिए
  • ln -fsकरने के लिए echo ln -fsएक सूखी रन के लिए

स्पष्टीकरण:

  • target="$(realpath "$l")" - सिमलिंक लक्ष्य के लिए पूर्ण पथ पाता है
  • ln -fs- मौजूदा के पुनर्लेखन के -sलिए सिम्लिंक ( ), मजबूर ( -f) बनाता है
  • realpath -s "$l" - अपने आप को सिमिलिंक करने के लिए निरपेक्ष मार्ग ढूंढता है
  • dirname "$(realpath -s "$l")" - सिम्लिंक युक्त निर्देशिका के लिए पूर्ण पथ पाता है
  • realpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target" - दूसरे शब्दों में, सिम्लिंक के सापेक्ष लक्ष्य का मार्ग खोजता है: सापेक्ष पथ से पूर्ण रूपांतरित होता है

1
मैं ifटूटे हुए लिंक को छोड़ने के लिए एक खंड जोड़ने का सुझाव दूंगा।
फूएनफंडैचटिजिग

0

इस बैश स्निपेट को करना चाहिए। पहला फॉर्म प्रिंट करेगा कि वह क्या करेगा; दूसरा करेगा। मैं ध्यान से आउटपुट की समीक्षा करूंगा क्योंकि यह विनाशकारी है - ln -fमौजूदा लिंक को ओवरराइट करता है।

TOP=/home/user/system
cd $TOP
find * -type l -print | while read l; do echo ln -sf $TOP$(readlink $l) $l; done
find * -type l -print | while read l; do      ln -sf $TOP$(readlink $l) $l; done

इस तथ्य के अलावा कि यह रिक्त स्थान वाले नामों के लिए असफल होगा, क्या यह गलत तरीका नहीं है? यह पूर्ण पथ को उपसर्ग करता है?
फेनफंडैचटिजिग

0

यहाँ एक शुद्ध श उपाय है।

सीडी / घर / उपयोगकर्ता / प्रणाली और&
खोजो। -Lname '/ *' |
पढ़ते समय l; करना
  echo ln -sf $ (echo $ (echo $ l | sed 's | / [^ /] / | / .. | g') $ (readlink $ l) | sed 's /.....//' ) $ ल
हो गया |
श

0

सापेक्ष लिंक में निरपेक्ष ट्रांसफ़ॉर्मिंग sshfs द्वारा समर्थित है जो ssh के माध्यम से दूरस्थ निर्देशिकाओं को मापता है।

आज्ञा है: वहाँ

sudo sshfs <remote_user>@<remote_ip_address>:/ /home/<host_user>/mntpoint/ -o transform_symlinks -o allow_other

आदेश, विशेष रूप से <placeholders>, विशिष्ट वातावरण के लिए अनुकूलित किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.