प्रतीकात्मक लिंक के बिना सापेक्ष पथ को परिवर्तित करना


63

क्या एक सापेक्ष पथ से निरपेक्ष (और विहित) पथ प्राप्त करने के लिए एक यूनिक्स कमांड है जिसमें प्रतीकात्मक लिंक शामिल हो सकते हैं?

जवाबों:


79

आप विकल्प के readlinkसाथ उपयोगिता का उपयोग कर सकते हैं -f:

-f, --canonicalize

      canonicalize  by  following  every symlink in every component of
      the given name recursively; all  but  the  last  component  must
      exist

कुछ वितरण, उदाहरण के लिए जो कि GNU कोरुटिल्स और फ्रीबीएसडी का उपयोग करते हैं , वे भी एक realpath(1)उपयोगिता के साथ आते हैं जो मूल रूप से सिर्फ कॉल realpath(3)करता है और बहुत ही समान काम करता है।


16
-fस्विच मैक ओएस एक्स (कम से कम 10.8.5 के रूप में) पर मौजूद नहीं है। -fस्विच के बिना यह सिर्फ एक त्रुटि कोड देता है।
आइकनोकॉस्ट

3
कुछ सिस्टम विशेष रूप से न तो readlinkऔर न ही realpath- सोलारिस और एचपी-यूएक्स के साथ आते हैं ।
सिल्डोरेथ

मैक समस्या के लिए: brew install coreutils apple.stackexchange.com/a/69332/23040 , और यदि आप ऐसा कदम नहीं करना चाहते हैं जो सभी मानक मैक CLI टूल्स को नए-स्थापित GNU समकक्षों के लिए पुनर्निर्देशित करे, बस कॉल करें greadlink
एड्रियन

18

विशेष रूप से, PWDचर को वर्तमान निर्देशिका के एक पूर्ण स्थान पर शेल द्वारा सेट किया जाता है। उस पथ का कोई भी घटक एक प्रतीकात्मक लिंक हो सकता है।

case $f in
  /*) absolute=$f;;
  *) absolute=$PWD/$f;;
esac

यदि आप समाप्त करना चाहते हैं .और ..साथ ही, निर्देशिका युक्त फ़ाइल में बदलें और $PWDवहां प्राप्त करें :

if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}

प्रतीकात्मक लिंक का अनुसरण करने का कोई पोर्टेबल तरीका नहीं है। यदि आपके पास निर्देशिका के लिए एक रास्ता है, तो अधिकांश यूनियनों में $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)एक पथ प्रदान किया जाता है जो प्रतीकात्मक लिंक का उपयोग नहीं करता है, क्योंकि जो गोले प्रतीकात्मक लिंक को ट्रैक करते हैं वे pwd -P"भौतिक" के लिए "पी" लागू करते हैं ।

कुछ इकाइयाँ "भौतिक" पथ को एक फ़ाइल में प्रिंट करने के लिए एक उपयोगिता प्रदान करती हैं।

  • यथोचित हाल ही में लिनक्स सिस्टम (GNU कोरुटिल्स या बिजीबॉक्स के साथ) readlink -f, जैसे कि FreeBSD .38.3, NetBSD Net4.0, और OpenBSD जहां तक ​​2.2 है।
  • FreeBSD some4.3 में realpath(यह कुछ लिनक्स सिस्टम पर भी मौजूद है, और यह बिजीबॉक्स में है)।
  • यदि पर्ल उपलब्ध है, तो आप Cwdमॉड्यूल का उपयोग कर सकते हैं ।

    perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file

आप कुछ pwd( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)) में पाइप क्यों डालते हैं ? यह स्टड की परवाह नहीं करता है।
मट्टुसज़ पिओत्रोस्की

1
@ मतेसज़पियोट्रोस्की टाइपो, मेरा लिखने का मतलब था||
गाइल्स

5

है pwdअपनी आवश्यकताओं के लिए फिट? यह वर्तमान निर्देशिका का पूर्ण मार्ग देता है। या हो सकता है कि आप जो चाहते हैं वह realpath () हो


3

alisterऔर rss67में इस लेख , सबसे अधिक स्थिर संगत और आसान तरीका परिचय। मैंने इससे बेहतर तरीका पहले कभी नहीं देखा।

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`

यदि आप मूल स्थान पर वापस जाना चाहते हैं,

ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH

या

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -

काश यह मदद करता। यह मेरे लिए सबसे बड़ा समाधान था।


12
यह वास्तव में इतना अच्छा तरीका नहीं है। एक निर्देशिका से बाहर और वापस बदलना विश्वसनीय नहीं है: आपके पास वापस आने की अनुमति नहीं हो सकती है, या इस बीच निर्देशिका का नाम बदल दिया गया हो सकता है। इसके बजाय, एक उपधारा में निर्देशिकाओं को बदलें ABSPATH=$(cd -- "$RELPATH" && pwd):। प्रतिस्थापन के चारों ओर दोहरे उद्धरणों पर ध्यान दें (ताकि यदि मार्ग में व्हॉट्सएप और ग्लोबिंग वर्ण शामिल न हों) और --(यदि पथ के साथ शुरू होता है -)। इसके अलावा यह केवल निर्देशिकाओं के लिए काम करता है, और अनुरोध के अनुसार प्रतीकात्मक लिंक को कैनोनिकलाइज़ नहीं करता है। अधिक जानकारी के लिए मेरा जवाब देखें।
गिलीस

"" आपके पास वापस आने की अनुमति नहीं हो सकती है "आपका मतलब सीडी से dir है लेकिन वापस सीडी नहीं कर सकता है? क्या आप कुछ उदाहरण परिदृश्य प्रदान कर सकते हैं।
तलस्पिन_कीट

0

यहाँ अन्य उत्तर ठीक थे लेकिन मेरी जरूरतों के लिए अपर्याप्त थे। मुझे एक समाधान की आवश्यकता थी जिसका उपयोग मैं किसी भी मशीन पर अपनी स्क्रिप्ट में कर सकता था। मेरा समाधान एक शेल स्क्रिप्ट लिखना था जिसे मैं उन लिपियों से प्राप्त कर सकता हूं जहां मुझे इसकी आवश्यकता है।

#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
  printf 'Usage: respath path [working-directory]\n' >&2
  exit 1
fi
cantGoUp=

path=$1
if [ $# -gt 1 ]; then
  cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks

#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
  printf '%s\n' "$path"
  exit 0
fi

#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
  case "$path" in
    ..*)
      if [ "$cwd" = '/' ]; then
        printf 'Invalid relative path\n' >&2
        exit 1
      fi
      if [ "$path" = '..' ]; then
        path=
      else
        path=`echo "$path" | sed 's;^\.\./;;'`
      fi
      cwd=`dirname $cwd`
      ;;
    *)
      break
      ;;
  esac
done

cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
  if [ -z "$cwd" ]; then
    cwd='/'
  fi
  printf '%s\n' "$cwd"
else
  printf '%s/%s\n' "$cwd" "$path"
fi

यह समाधान पोर्टेबिलिटी के लिए बॉर्न शेल के लिए लिखा गया है। मेरे पास "respath.sh" नाम की एक स्क्रिप्ट है।

इस लिपि का उपयोग इस तरह किया जा सकता है:

respath.sh '/path/to/file'

या इस तरह

respath.sh '/relative/path/here' '/path/to/resolve/relative/to'

स्क्रिप्ट शुरुआती तर्क के रूप में दूसरे तर्क से पथ का उपयोग करके पहले तर्क में पथ को हल करता है। यदि केवल पहला तर्क प्रदान किया जाता है, तो स्क्रिप्ट आपकी वर्तमान कार्यशील निर्देशिका के सापेक्ष पथ को हल करती है।


ध्यान दें कि आप शायद सोलारिस 10 और इससे पहले आजकल एक बॉर्न खोल पाएंगे। यही कारण है कि बॉर्न SVR2 के बाद से सबसे बॉर्न शैल कार्यान्वयन की तरह शेल (1984) है pwdbuiltin और समर्थन नहीं करता -P(बॉर्न शैल कि तार्किक $ पीडब्ल्यूडी POSIX के गोले की तरह से निपटने कर लागू नहीं किया)।
स्टीफन चेज़लस

यदि आप बॉर्न अनुकूलता को गिराते हैं, तो आप POSIX $ {var ## पैटर्न} सिंटैक्स का उपयोग कर सकते हैं और उन प्रतिध्वनि से बच सकते हैं। जो कुछ मूल्यों के साथ टूटने वाली हैं।
स्टीफन चेज़लस

Cd (और pwd) की निकास स्थिति की जांच करना भूल जाते हैं। संभवत: cd -P --1 तर्क में कुछ शामिल होने पर आपको इसका उपयोग करना चाहिए ..
स्टीफन चेज़लस

इसके बजाय आपका caseचेक होना चाहिए । ..|../*)..*
स्टीफन चेज़लस

वहाँ लापता उद्धरण का एक मामला हैdirname $cwd
स्टीफन चेज़ेलस

0

मामले में, इसके अतिरिक्त, आपके पास $1(आमतौर पर ${PWD}) के लिए कुछ पूर्वनिर्धारित मार्ग हैं , निम्नलिखित काम करेंगे:

CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
    case $1 in
        /*) echo "CWD=${CWD}"; ;;
        *) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
    esac
fi

0

हर किसी के जवाब का सम्मान करते हुए, मैंने नीचे दिए गए फ़ंक्शन को लिनक्स / मैक ओएसएक्स के बीच बहुत आसान और पोर्टेबल पाया, जो मुझे हर जगह मिला था। किसी की मदद कर सकते हैं।

#!/usr/bin/bash
get_absolute_path(){
    file_path=`pwd $1`
    echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path

-1

मान लें कि चर एक पथ का नाम है (a = "जो भी")

1. संभावित अंतरिक्ष युक्त पथ के लिए:

c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi

2. वास्तविक प्रश्न के लिए, अर्थात पथ को निरपेक्ष में परिवर्तित करना: रीडिंकल सिम्लिंक सामग्री को पुनः प्राप्त कर सकता है, जिसे निम्नानुसार नियोजित किया जा सकता है। (नोट readlink -fसही हो गया होता लेकिन कम से कम मैक ओएस एक्स पार्टी है, जिसमें में उपलब्ध नहीं है -f के लिए खड़ा है प्रारूप ।)

if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi

3. बस सीखा pwd -Pमें man pwd: -पी "करने के लिए है शारीरिक वर्तमान कार्यशील निर्देशिका प्रदर्शित करें (सभी सांकेतिक लिंक का समाधान) " और इसलिए

if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)

काम भी करेगा।

निष्कर्ष: अपनी दोनों आवश्यकताओं को पूरा करने के लिए 1 को 2 के साथ मिलाएं, जबकि अधिक संक्षिप्त 3 में अंतरिक्ष युक्त पथ नामों का पहले से ही ख्याल रखा गया है ।


आप (र) संयुक्त गलत है। उदाहरण के लिए, यदि आपके पथ में उपरोक्त अभ्यस्त कार्य के लिए एक स्थान शामिल है।
एंथन

या एक ग्लोब चार कभी कभी। और यह सिमिलिंक को हल नहीं करता है, जैसा कि अनुरोध किया गया था।
dave_thompson_085

मैंने रिक्त स्थान वाले पथ नामों के बारे में अपनी "टिप्पणी" प्रतिक्रिया हटा दी है और तदनुसार "उत्तर" भाग को संशोधित किया है।
vxtal
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.