OS X से मनमानी फ़ाइल के पूर्ण पथ को कैसे पुनः प्राप्त करें


18

मैं एक साधारण कमांड की तलाश कर रहा हूं जिसका उपयोग ओएस एक्स पर फ़ाइल के लिए निरपेक्ष और कैनोनिकलकृत पथ को खोजने के लिए किया जा सकता है (लिनक्स के नीचे `` रीडलिंक -f'` के समान)।

निम्नलिखित नमूना बैश सत्र एक [काल्पनिक] उपयोगिता का वर्णन करता है जिसे `` abspath'` कहा जाता है जो वांछित व्यवहार प्रदर्शित करता है:

$ pwd
/Users/guyfleegman

$ ls -lR
drwxr-xr-x  4 guyfleegman  crew  136 Oct 30 02:09 foo

./foo:
-rw-r--r--  1 guyfleegman  crew  0 Oct 30 02:07 bar.txt
lrwxr-xr-x  1 guyfleegman  crew  7 Oct 30 02:09 baz.txt -> bar.txt


$ abspath .
/Users/guyfleegman

$ abspath foo
/Users/guyfleegman/foo

$ abspath ./foo/bar.txt
/Users/guyfleegman/foo/bar.txt

$ abspath foo/baz.txt
/Users/guyfleegman/foo/baz.txt

उपरोक्त उदाहरण में `` abspath'` के अंतिम आह्वान के साथ, मैं पसंद करूँगा कि यह स्वचालित रूप से सहानुभूति का समाधान न करे, लेकिन मैं यहाँ बहुत ज्यादा नहीं जा रहा हूँ।


जवाबों:


16
function abspath() { pushd . > /dev/null; if [ -d "$1" ]; then cd "$1"; dirs -l +0; else cd "`dirname \"$1\"`"; cur_dir=`dirs -l +0`; if [ "$cur_dir" == "/" ]; then echo "$cur_dir`basename \"$1\"`"; else echo "$cur_dir/`basename \"$1\"`"; fi; fi; popd > /dev/null; }

उदाहरण:

abspath / => /

abspath /.DS_Store => /.DS_Store

abspath ~ => /Users/mschrag

cd /tmp; abspath . => /tmp

cd /; abspath .DS_Store => /.DS_Store

11

मुझे नहीं लगता कि इसमें कोई बिल्डिन कमांड है जो ऐसा करता है। जेसी विल्सन ने इसके लिए एक बैश स्क्रिप्ट लिखी:

#!/bin/bash
cd -P -- "$(dirname -- "$1")" &&
printf '%s\n' "$(pwd -P)/$(basename -- "$1")"

हालांकि, यह सीधे नीचे दिए गए रास्तों के लिए अच्छी तरह से काम नहीं करता है /, जैसे /etc(मुद्रण //etc), साथ ही .और ..( /cwd/.दोनों मामलों में मुद्रण )। मैंने इसे संशोधित करने की कोशिश की, लेकिन मेरे असफल बास-फू ने मुझे विफल कर दिया।

यहाँ मेरा सुझाव है:

#!/usr/bin/env python
import os.path
import sys

for arg in sys.argv[1:]:
    print os.path.abspath(arg)

के रूप में /usr/bin/abspathया ऐसा कुछ बचाओ और इसे निष्पादन योग्य बनाओ। नमूना उत्पादन:

Servus08:~ danielbeck$ abspath .
/Users/danielbeck
Servus08:~ danielbeck$ abspath /tmp
/tmp
Servus08:~ danielbeck$ abspath Documents
/Users/danielbeck/Documents
Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/tmp
/Users/danielbeck/Documents

यदि आप करते हैं सिमलिंक संकल्प चाहते हैं, बदल printइस तरह लाइन:

    print os.path.realpath(os.path.abspath(arg))

इसे पाने के लिए:

Servus08:~ danielbeck$ abspath . /tmp Documents
/Users/danielbeck
/private/tmp
/Users/danielbeck/Documents

1
मुझे लगता है कि आप पहले शेल-आधारित दृष्टिकोण के साथ सही रास्ते पर हैं, लेकिन मेरा मानना ​​है कि ऐसा करने के लिए किसी अन्य भाषा का उपयोग करना कुछ हद तक उद्देश्य को हरा देता है, क्योंकि यह अतिरिक्त निर्भरता का परिचय देता है और जीएनयू के `रीडलिंक के संस्करण को संकलित करने के लिए बहुत अधिक समकक्ष है। (1) 'ओएस एक्स के तहत (यह माना जा सकता है; मैंने अभी तक इसे सत्यापित नहीं किया है)।
माइकल वीन्नर

2
@ मिचेल आप या तो जीएनयू रीडिंकल के साथ एक प्रणाली पर हैं, या ओएस एक्स पर - सही? OS X में बॉक्स से बाहर पायथन है। सिद्धांत रूप में यह एक नई निर्भरता है, व्यवहार में नहीं। वैसे भी, यह सब मैं आप की पेशकश कर सकता है।
डैनियल बेक

यदि आप अत्यधिक सरल हैं, तो आप जिस व्यावहारिक दृष्टिकोण का उपयोग कर रहे हैं वह प्रशंसनीय है। किसी भी मामले में, अगर हम विशुद्ध रूप से बैश में लिखी गई किसी भी चीज़ के बदले में यह तरीका अपनाते हैं (जो कि बिल्कुल उल्लेखनीय है और किसी और चीज़ पर निर्भर नहीं करता है - यह आसानी से एक पंक्ति में नहीं किया जा सकता है), पायथन शायद नहीं है 'सबसे अच्छा विकल्प नहीं है। पर्ल और रूबी (और शायद PHP) दोनों एक वास्तविक स्क्रिप्ट फ़ाइल बनाने की आवश्यकता के बिना कमांड लाइन पर सफलतापूर्वक ऐसा कर सकते हैं।
माइकल वेनर

1
@ माइकल: सच, लेकिन यह वह नहीं है जिस पर मैं टिप्पणी कर रहा था। मैं आपको जेसी विल्सन + द्वारा विशुद्ध बाश में लिखे गए 90% समाधान की पेशकश करता हूं + यह विश्लेषण केवल 90% क्यों है। अगर आपके लिए कोई समस्या नहीं है, तो यह ठीक है। मैंने आपको पायथन में 100% समाधान के लिए थोड़ा और अधिक जटिल दिया। जबकि अन्य स्क्रिप्टिंग भाषाएं briefer हो सकती हैं (Perl बदनाम इतनी :-)), सभी को कमांड स्टोर करने के लिए एक अतिरिक्त फाइल की आवश्यकता होती है। या क्या आप इसे हर बार लिखना चाहते हैं जब आप इसका उपयोग करना चाहते हैं? यही कारण है कि मैंने मल्टी-लाइन क्षमता को कई मापदंडों को संभालने के लिए जोड़ा, 1 या 2 लाइनें फिर एक अलग नहीं बनाते हैं।
डैनियल बेक

2
@ माइकल, OS X पर पायथन एक अच्छा विकल्प क्यों नहीं होगा? यहां तक ​​कि यह उन कमांडों के साथ भी जहाज है जो वास्तव में पायथन स्क्रिप्ट हैं, जैसेfile /usr/bin/xattr
अर्जन

8

एक विकल्प सिर्फ कोरयूटिल्स स्थापित करना और उपयोग करना होगा greadlink -f। यह सिमलिंक हल करता है और इसके साथ काम करता है /Foo/या ~/foo.txtयदि वे मौजूद नहीं है, लेकिन नहीं के साथ /Foo/foo.txtकरता है, तो /Foo/मौजूद नहीं है।

$ brew install coreutils
$ greadlink -f /etc
/private/etc
$ greadlink -f ~/Documents/
/Users/lauri/Documents
$ greadlink -f ..
/Users
$ greadlink -f //etc/..////
/private
$ greadlink -f /Foo
/Foo
$ greadlink -f /Foo/foo.txt
$ 

यह सीमलिंक को हल नहीं करता है, और यह किसी भी तरह से काम नहीं करता है /Foo/foo.txt

abspath() {
  if [ -d "$1" ]; then
    ( cd "$1"; dirs -l +0 )
  else
    ( cd "$(dirname "$1")"; d=$(dirs -l +0); echo "${d%/}/${1##*/}" )
  fi
}

abspath /etc # /etc
abspath ~/Foo/foo.txt # doesn't work
abspath ~/Foo # works
abspath .
abspath ./
abspath ../
abspath ..
abspath /
abspath ~
abspath ~/
abspath ~/Documents
abspath /\"\ \'
abspath /etc/../etc/
abspath /private//etc/
abspath /private//
abspath //private # //private
abspath ./aa.txt
abspath aa.tar.gz
abspath .aa.txt
abspath /.DS_Store
abspath ~/Documents/Books/

dirs -lटिल्ड विस्तार करता है। dirs +0यदि स्टैक में अन्य निर्देशिका हैं, तो केवल सबसे ऊपरी निर्देशिका प्रिंट करता है।


2

मुझे लगता है कि आप इसे अजगर या माणिक के साथ कर सकते थे।

$ ruby -e 'puts File.expand_path("~/somepath")'

या इसके साथ एक कमांड बनाएं

#!/usr/bin/env ruby
puts File.expand_path(ARGV[0])

डैनियल बेक के उत्तर पर मेरी पहले की टिप्पणी यहाँ भी लागू होती है (मैं विशुद्ध रूप से बैश-वाई समाधान पसंद करूँगा), हालाँकि अगर मैं इसे प्राप्त करने के लिए किसी अन्य भाषा का उपयोग करने का सहारा ले रहा था, तो मुझे इसकी संक्षिप्तता के लिए आपका समाधान सबसे अच्छा लगता है। :) मैं भी शायद माणिक को कॉल लपेट दूंगा (जैसे फंक्शन अबस्पाट () {माणिक-ई) "File.expand_path ('$ 1')";) डालता है और इसे मेरे `प्रॉफ़ाइल 'में डाल देता है।
माइकल वीन्हेर

1

यदि आपके पास फ़ाइल :: पर्ल के लिए विशिष्ट मॉड्यूल स्थापित है, तो आप ऐसा कर सकते हैं:

perl -MFile::Spec -e 'print File::Spec->rel2abs("../however/complex/../you/want/to.get"), "\n"'

0

बैश / श स्क्रिप्ट के लिए आप इस पुनरावर्ती फ़ंक्शन का उपयोग कर सकते हैं:

canonical_readlink ()
{
    cd `dirname $1`;
    __filename=`basename $1`;
    if [ -h "$__filename" ]; then
        canonical_readlink `readlink $__filename`;
    else
        echo "`pwd -P`";
    fi
}

answer=$(canonical_readlink $0)

कुछ चर और कमांड प्रतिस्थापन ठीक से उद्धृत नहीं किए गए हैं। आप जैसे चर नामों के बजाय स्थानीय चर का उपयोग कर सकते हैं __filename। वर्तमान में स्क्रिप्ट dirnameवैसे भी अधिक व्यवहार करती है।
20

0

OSX के लिए निम्नलिखित पुस्तकालय स्थापित करें:

brew install coreutils

greadlink -f file.txt

0

यदि कोरुटिल्स स्थापित करना एक विकल्प नहीं है, तो निम्नलिखित सिम्बलिंक के कॉम्बो को संभालता है, और .. और GNU realpath जैसी फ़ाइलों और फ़ोल्डरों पर काम करता है:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

लेकिन यह realpath के --relative-to का समर्थन नहीं करता है। इसके लिए आवश्यकता होगी /programming//a/12498485/869951 की


0

यह देखते हुए कि बाधा MacOS (OS X उस समय) है, PHP डिफ़ॉल्ट रूप से उपलब्ध है। यह फ़ाइल की रूट डायरेक्टरी लौटाएगा। dirnameफ़ाइल प्राप्त करने के लिए भी निकालें ।

export SOURCE_DIRECTORY="$(php -r 'echo dirname(realpath($argv[1]));' -- "${BASH_SOURCE[0]}")"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.