क्या आप इसे बनाने के बाद एक सिमलिंक को बदल सकते हैं?


122

क्या कोई ऑपरेटिंग सिस्टम एक प्रतीकात्मक लिंक (सिमिलिंक) द्वारा संदर्भित पथनाम को बदलने के लिए एक तंत्र (सिस्टम कॉल - कमांड लाइन प्रोग्राम नहीं) प्रदान करता है - पुराने को हटाकर एक नया बनाने के अलावा?

POSIX मानक नहीं है। सोलारिस 10 नहीं है। MacOS X 10.5 (तेंदुआ) नहीं है। (मैं पूरी तरह से निश्चित रूप से न तो एआईएक्स और न ही एचपी-यूएक्स या तो करता हूं। लिनक्स सिस्टम कॉल की इस सूची को देखते हुए , लिनक्स में ऐसी प्रणाली कॉल भी नहीं है।)

क्या ऐसा कुछ है?

(मुझे उम्मीद है कि जवाब "नहीं" है।)


चूंकि एक नकारात्मक साबित करना कठिन है, आइए प्रश्न को पुनर्गठित करें।

यदि आप जानते हैं कि कुछ (यूनिक्स की तरह) ऑपरेटिंग सिस्टम पहले से ही सूचीबद्ध नहीं है readlink(), तो पुराने सिम्कलिन को हटाए बिना और नया बनाने के लिए सिम्लिंक (स्ट्रिंग द्वारा लौटाए गए ) का मान दोबारा लिखने के लिए कोई सिस्टम कॉल नहीं है , कृपया इसे जोड़ें - या उन्हें - एक उत्तर में।


केवल राहत देने में क्या गलत है? lnपुराने लिंक को अधिलेखित करने के लिए केवल कमांड (या एपीआई समतुल्य) क्यों नहीं जारी किया जाता है ? आपकी क्या समस्या हैं?
S.Lott

9
मजेदार - मैं पूछ रहा हूं कि क्या एक प्रोग्रामिंग काम करने के लिए एक सिस्टम कॉल है, और यह प्रश्न चिह्नित किया जा रहा है कि 'अन्य साइट पर है'।
जोनाथन लेफ़लर

3
मजेदार- यह बिल्कुल स्पष्ट नहीं था कि आप एक सिस्टम कॉल की तलाश में थे और आपने इस विवरण को जोड़ने के लिए प्रश्न को संपादित किया। तो इससे पहले कि आप इसे लिखने से पहले लोगों से कुछ कटौती करने की उम्मीद कैसे करें?
पास्कल थिवेंट

2
@ S.Lott: मैं सुरक्षा और प्रतीकात्मक लिंक पर एक पेपर लिख रहा हूं। एक बिंदु पर मैं यह दावा करता हूं कि "वास्तविक मालिक, समूह, सिम्लिंक पर अनुमतियाँ स्वयं ही सारहीन हैं" और तर्क यह है कि सिमलिंक का मालिक केवल इसे हटा सकता है और मूल्य नहीं बदल सकता है। मैं दोहरा जाँच कर रहा हूँ कि sym सिम्लिंक मान को फिर से लिखने ’के प्रभाव को प्राप्त करने के सिम्बल को हटाने के अलावा कोई रास्ता नहीं है। मैं कच्ची डिस्क तक सीधी पहुंच को अनदेखा कर रहा हूं और एफएस को हैक कर रहा हूं - इसके लिए रूट विशेषाधिकार की आवश्यकता है और मेरी चिंता गैर-रूट उपयोगकर्ताओं के साथ है, न कि यह कि रूट क्या कर सकता है।
जोनाथन लेफ़लर

4
@ पास्कल: मुझे क्षमा करें - मुझे यह महसूस नहीं हुआ कि यह स्पष्ट नहीं था कि मैं सिस्टम कॉल के बारे में बात कर रहा था जब तक कि लोग मेरे इरादे से एक स्पर्शरेखा पर नहीं चले गए (जो कि मेरे कहे अनुसार स्पष्ट रूप से अलग था)। मुझे गुमराह होने के लिए खेद है; यह अनजाने में था।
जोनाथन लेफ़लर

जवाबों:


106

AFAIK, नहीं, आप नहीं कर सकते। आपको इसे हटाकर इसे फिर से बनाना होगा। वास्तव में, आप एक सिम्कल को अधिलेखित कर सकते हैं और इस प्रकार इसके द्वारा संदर्भित पथनाम को अद्यतन कर सकते हैं:

$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 8 2009-09-23 17:12 test -> .profile

संपादित करें : जैसा कि ओपी ने एक टिप्पणी में कहा है, --forceविकल्प का उपयोग lnकरने unlink()से पहले एक सिस्टम कॉल करना होगा symlink()। नीचे, straceमेरे लिनक्स बॉक्स पर इसे साबित करने का आउटपुट :

$ strace -o /tmp/output.txt ln -s -f .bash_aliases test
$ grep -C3 ^unlink /tmp/output.txt 
lstat64("test", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0
stat64(".bash_aliases", {st_mode=S_IFREG|0644, st_size=2043, ...}) = 0
symlink(".bash_aliases", "test")        = -1 EEXIST (File exists)
unlink("test")                          = 0
symlink(".bash_aliases", "test")        = 0
close(0)                                = 0
close(1)                                = 0

इसलिए मुझे लगता है कि अंतिम उत्तर "नहीं" है।

संपादित करें : निम्नलिखित को Arto Bendiken के unix.stackexchange.com, circa 2016 के उत्तर से कॉपी किया गया है ।

यह कर सकते हैं वास्तव में साथ atomically किया जाना rename(2)है, पहले एक अस्थायी नाम के तहत नए सिमलिंक बनाने और फिर सफाई से एक ही बार में वर्ष सिमलिंक ओवरराइट करके। जैसा कि मैन पेज बताता है:

यदि newpath एक प्रतीकात्मक लिंक को संदर्भित करता है तो लिंक को ओवरराइट कर दिया जाएगा।

शेल में, आप इसे mv -Tनिम्नानुसार करेंगे:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

आप straceयह सुनिश्चित कर सकते हैं कि यह वास्तव rename(2)में हुड के नीचे उपयोग कर रहा है:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

नोट ऊपर में है कि, दोनों mv -Tऔर straceकर रहे हैं लिनक्स विशिष्ट।

FreeBSD पर, mv -hवैकल्पिक रूप से उपयोग करें ।

संपादक का ध्यान दें: यह कैसे Capistrano ने वर्षों के लिए किया है, अब ~ 2.15 के बाद से। यह पुल अनुरोध देखें ।


2
क्या '-f' विकल्प बल 'ln' को अनलिंक करने के लिए नहीं करता है?
जोनाथन लेफ्लर

1
ऐसा होता है। लेकिन सवाल यह माना गया है कि "मैं एक कदम में ऐसा कैसे कर सकता हूं" और फिर यह "चरण" की परिभाषा को उबालता है - कमांड लाइन? syscall?
माइकल क्रेलिन -

1
मैंने अभी-अभी ध्यान दिया है कि आपने syscall
वर्डिंग

2
@ पास्कल: यह करता है। सोलारिस पर, 'ट्रस ln -spx' और 'ट्रस ln -s -fpx' से आउटपुट दूसरे मामले में सिम्कलिन () कॉल से पहले एक अनलिंक () कॉल दिखाता है (और पहले में एक फेल्ड सिमलिंक () कॉल)। मुझे उम्मीद है कि यूनिक्स के सभी वेरिएंट के लिए सबसे अधिक लागू होगा।
जोनाथन लेफ्लर 16

12
+1 से @ टायई टिप्पणी - यदि एक सिरिंकल से निपटने के लिए जो एक निर्देशिका को संदर्भित करता है (अंक), तो आपको यह चाल काम करने के लिए "-n" निर्दिष्ट करने की आवश्यकता है।
वैली

161

हाँ तुम कर सकते हो!

$ ln -sfn source_file_or_directory_name softlink_name

9
जवाब देने के लिए धन्यवाद। -fविकल्प का अर्थ है नया बनाने से पहले 'मौजूदा गंतव्य को दूर'। तो, यह कमांड परिणाम प्राप्त करता है, लेकिन unlink(2)इसके बाद करता है symlink(2)। यह वह नहीं है जो मूल प्रश्न के बारे में था। यह भी ध्यान दें कि स्वीकृत उत्तर और अगला सबसे अधिक वोट किया गया उत्तर दोनों ln -sfकाम करने के लिए उपयोग करते हैं, लेकिन जैसा कि straceआउटपुट दिखाता है, यह करता है unlink()और symlink()क्योंकि सिम्लिंक को संशोधित करने के लिए सिस्टम कॉल नहीं है।
जोनाथन लेफलर

17
-N की आवश्यकता तब लगती है जब मूल लिंक किसी फ़ाइल के बजाय निर्देशिका में जाता है।
स्टीमपॉवर

11
'एन' स्विच महत्वपूर्ण है। मैं इस समस्या से जूझ रहा था कि सिमलिंक को अपडेट नहीं किया गया था, लेकिन कमांड ने मौजूदा एक के अंदर एक और लिंक बनाया क्योंकि 'नो डेरीफेंसिंग' विकल्प सेट नहीं था।
जोनाथन ग्रुबर

14

पुराने सिम्लिंक को स्पष्ट रूप से अनलिंक करना आवश्यक नहीं है। तुम यह केर सकते हो:

ln -s newtarget temp
mv temp mylink

(या समतुल्य सीलिंक और नाम बदलें कॉल का उपयोग करें)। यह स्पष्ट रूप से अनलिंक करने से बेहतर है क्योंकि नाम परमाणु है, इसलिए आपको यह आश्वासन दिया जा सकता है कि लिंक हमेशा पुराने या नए लक्ष्य को इंगित करेगा। हालांकि यह मूल इनोड का पुन: उपयोग नहीं करेगा।

कुछ फाइलसिस्टम पर, सिंपलिंक का लक्ष्य इनकोड में ही संग्रहीत किया जाता है (ब्लॉक सूची के स्थान पर) यदि यह पर्याप्त छोटा है; इसे उस समय बनाया जाता है जब इसे बनाया जाता है।

वास्तविक मालिक और समूह के सारहीन होने के दावे के बारे में, लिनक्स पर सिमिलिंक (7) का कहना है कि एक ऐसा मामला है जहां यह महत्वपूर्ण है:

एक मौजूदा प्रतीकात्मक लिंक के मालिक और समूह को lchown (2) का उपयोग करके बदला जा सकता है। केवल एक बार जब प्रतीकात्मक लिंक मामलों का स्वामित्व तब होता है जब लिंक को हटाया जा रहा है या एक निर्देशिका में नाम बदला गया है जिसमें चिपचिपा बिट सेट है (देखें स्टेट (2))।

एक प्रतीकात्मक लिंक के अंतिम उपयोग और अंतिम संशोधन टाइमस्टैम्प को यूटेंसैट (2) या lutimes (3) का उपयोग करके बदला जा सकता है।

लिनक्स पर, किसी भी ऑपरेशन में एक प्रतीकात्मक लिंक की अनुमति का उपयोग नहीं किया जाता है; अनुमतियाँ हमेशा 0777 हैं (सभी उपयोगकर्ता श्रेणियों के लिए पढ़ें, लिखें, और निष्पादित करें), और उन्हें बदला नहीं जा सकता।


@ mark4o: द गुड - एक स्टिकी-इट डायरेक्टरी में lchown () और स्वामित्व का संदर्भ उपयोगी है - धन्यवाद। मैं lchown के बारे में पता था () और यह मेरे थीसिस के लिए भौतिक नहीं था। मुझे चिपचिपी-बिट निर्देशिकाओं के बारे में भी पता था; मुझे लगता है कि स्वामित्व लगभग नियमों का एक मानक परिणाम है - अंतर, और संभवतः इसे बाहर क्यों कहा जाता है, क्या यह है कि आम तौर पर आप एक फ़ाइल को निकाल सकते हैं यदि आप इसे लिख सकते हैं, और नाममात्र, कोई भी एक सिम्लिंक को लिख सकता है क्योंकि 777 अनुमतियाँ, लेकिन इस मामले में, नियम थोड़े अलग हैं।
जोनाथन लेफ्लर

1
@ mark4o: नहीं तो अच्छा है - दिखाया गया कमांड क्रम वह नहीं करता है जो आपको लगता है कि यह करता है (कम से कम, परिदृश्य में:) set -x -e; mkdir junk; ( cd junk; mkdir olddir newdir; ln -s olddir mylink; ls -ilR; ln -s newdir temp; ls -ilR; mv temp mylink; ls -ilR; ); rm -fr junk। यदि आप निर्देशिकाओं के बजाय पुरानी और नई फ़ाइल बनाते हैं, तो समान स्क्रिप्ट (मुख्य रूप से पुराने को पुराने से पुराने में बदलना, नए से नए को बदलना), तो आप वह प्रभाव प्राप्त करते हैं जिसकी आप अपेक्षा कर रहे थे। बस एक अतिरिक्त जटिलता! जवाब देने के लिए धन्यवाद।
जोनाथन लेफ्लर

2

उपरोक्त सही उत्तरों के लिए बस एक चेतावनी:

यदि आप स्रोत और लक्ष्य को मिलाते हैं, तो -f / --force विधि का उपयोग फ़ाइल को खोने का जोखिम प्रदान करता है:

mbucher@server2:~/test$ ls -la
total 11448
drwxr-xr-x  2 mbucher www-data    4096 May 25 15:27 .
drwxr-xr-x 18 mbucher www-data    4096 May 25 15:13 ..
-rw-r--r--  1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
-rw-r--r--  1 mbucher www-data 7582480 May 25 15:27 otherdata.tar.gz
lrwxrwxrwx  1 mbucher www-data      11 May 25 15:26 thesymlink -> data.tar.gz
mbucher@server2:~/test$ 
mbucher@server2:~/test$ ln -s -f thesymlink otherdata.tar.gz 
mbucher@server2:~/test$ 
mbucher@server2:~/test$ ls -la
total 4028
drwxr-xr-x  2 mbucher www-data    4096 May 25 15:28 .
drwxr-xr-x 18 mbucher www-data    4096 May 25 15:13 ..
-rw-r--r--  1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
lrwxrwxrwx  1 mbucher www-data      10 May 25 15:28 otherdata.tar.gz -> thesymlink
lrwxrwxrwx  1 mbucher www-data      11 May 25 15:26 thesymlink -> data.tar.gz

बेशक यह इरादा है, लेकिन आमतौर पर गलतियां होती हैं। इसलिए, सिमलिंक को हटाना और पुनर्निर्माण करना थोड़ा अधिक काम है लेकिन थोड़ा अधिक सुरक्षित है:

mbucher@server2:~/test$ rm thesymlink && ln -s thesymlink otherdata.tar.gz 
ln: creating symbolic link `otherdata.tar.gz': File exists

जो कम से कम मेरी फ़ाइल रखता है।


एक का उपयोग करना -fया --forceविकल्प हमेशा एक सा खतरनाक है; यह मानता है कि उपयोगकर्ता जानता है कि वे किस बारे में हैं। यदि आप इसे आदतन उपयोग करते हैं ( rm -fr …हर बार खतरनाक है) तो यह दोगुना घातक है।
जोनाथन लेफ़लर

1

इसे अनलिंक नहीं करना और नया बनाना वैसे भी अंत में एक ही काम करेगा?


2
पहली बार में अनलिंक क्यों? इसे सरल क्यों नहीं लिखा जाता है?
S.Lott

5
शुद्ध परिणाम लगभग समान है - लेकिन मालिक और समूह और अंतिम संशोधित समय (और शायद इनोड संख्या) सभी सामान्य रूप से अलग-अलग होंगे।
जोनाथन लेफ़लर

2
@ S.Lott: 'अधिलेखित' किस प्रणाली को कहते हैं? POSIX में, ऐसा कोई कॉल नहीं है। Solaris और MacOS X में, ऐसी कोई कॉल नहीं है। क्या ऐसा करने के लिए एक कॉल है ... लिनक्स, एआईएक्स, एचपी-यूएक्स, कुछ और जो यूनिक्स जैसा दिखता है? विंडोज में वास्तव में उसी तरह से सिम्फिंक्स नहीं है, एएफएआईसीटी, इसलिए यह मेरे विश्लेषण के लिए महत्वपूर्ण नहीं है - लेकिन समकक्ष विंडोज एपीआई के बारे में जानकारी उपयोगी होगी।
जोनाथन लेफ्लर 15

@ जोनाथन लेफ़लर: उम्म .... ln --forceकमांड मौजूदा लिंक को पूरी तरह से अधिलेखित कर देगा।
सल।

दोस्तों, मुझे लगता है कि आप क्रॉस उद्देश्यों पर बात कर रहे हैं। एस.लॉट एक निष्पादन योग्य पर चर्चा कर रहा है ln (1), जबकि मैट बी। इस तथ्य पर चर्चा कर रहा है कि ओवरराइटिंग का समर्थन नहींsymlink (2) करता है । आप दोनों सही हैं, और मैं सुझाव दूंगा कि कार्यान्वयन को देखते हुए अनलिंक-रिंकल प्रक्रिया को पूरा करने का सबसे मुहावरेदार तरीका दिया जाएगा। ln (1)
dmckee --- पूर्व-संचालक ने

0

बस मामले में यह मदद करता है: मिडनाइट कमांडर (mc) के साथ एक सिम्लिंक को संपादित करने का एक तरीका है। मेनू कमांड (मेरे mc इंटरफ़ेस पर फ्रेंच में) है:

Fichier / Éditer le lien symbolique

जिसका अनुवाद किया जा सकता है:

File / Edit symbolic link

शॉर्टकट Cx Cs है

शायद यह आंतरिक रूप से ln --forceकमांड का उपयोग करता है , मुझे नहीं पता।

अब, मैं एक ही बार में बहुत सारे सिम्बलिंक को संपादित करने का एक तरीका खोजने की कोशिश कर रहा हूं (यह है कि मैं यहां कैसे पहुंचा)।


1
क्या आपने सत्यापित किया है कि MC पर्दे के पीछे क्या करता है? मुझे लगता है कि वास्तव में यह एक unlink()द्वारा पीछा किया है symlink(), सिर्फ इसलिए कि यूनिक्स की तरह सिस्टम प्रदान करता है रखना होगा ।
जोनाथन लेफलर

नहीं, मैंने जाँच नहीं की है। और हां, यह काफी संभावना है कि जैसा कि आप कहते हैं, वास्तव में। यह तथ्य यह है कि मैं एक टेक्स्टबॉक्स संपादित करता हूं यह महसूस करता है कि मैं वास्तव में सिम्लिंक लक्ष्य को संपादित कर रहा हूं, लेकिन मुझे शायद मूर्ख बनाया गया है ...
पियरे

0

तकनीकी रूप से, मौजूदा प्रतीकात्मक लिंक को संपादित करने के लिए कोई अंतर्निहित कमांड नहीं है। इसे कुछ ही कम कमांड के साथ आसानी से हासिल किया जा सकता है।

यहाँ थोड़ा बैश / zsh फ़ंक्शन है जिसे मैंने एक मौजूदा प्रतीकात्मक लिंक को अद्यतन करने के लिए लिखा था:

# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with 
# -----------------------------------------
function edit-symlink () {
    if [ -z "$1" ]; then
        echo "Name of symbolic link you would like to edit:"
        read LINK
    else
        LINK="$1"
    fi
    LINKTMP="$LINK-tmp"
    if [ -z "$2" ]; then
        echo "Full destination path to update existing symlink with:"
        read DEST
    else
        DEST="$2"
    fi
    ln -s $DEST $LINKTMP
    rm $LINK
    mv $LINKTMP $LINK
    printf "Updated $LINK to point to new destination -> $DEST"
}

2
प्रयास के लिए धन्यवाद। यह C भाषा प्रणाली कॉल होने की मेरी आवश्यकता को पूरा नहीं करता है। किसी लिंक को बदलने के कई तरीके हैं जब तक कि आप लिंक को पकड़े निर्देशिका में अनुमति लिखते हैं (जिसके लिए यह आवश्यक है)। ऐसा कोई तरीका नहीं है जो मुझे पता है, यहां तक ​​कि अब भी, बिना किसी सिमिलिंक के मूल्य को बदलने के लिए unlink()और symlink()नए मूल्य के साथ, जो कि आपके कोड के साथ पर्दे के पीछे चलता है। व्यक्तिगत रूप से, मेरे पास फ़ंक्शन दो (या शायद दो में से कई) पर जोर देना होगा और अगर जमानत सही नहीं थी, तो जमानत दें। हालांकि यह एक विशेष दृष्टिकोण है।
जोनाथन लेफ़लर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.