2011-07-05 12 views
8

मैं पर्ल का उपयोग कर निर्देशिका में एक टूटी हुई सिम्लिंक को हटाना चाहता हूं।मैं कैसे पता लगा सकता हूं कि पर्ल में एक सिम्लिंक टूट गया है?

मेरे मन में मैं सिर्फ एक निर्देशिका की फ़ाइल सूची था और परीक्षण यह एक सिमलिंक (एल) है और अगर यह गलत रिटर्न सिर्फ लिंक हटाना।

लेकिन ऐसा लगता है कि जब readir का उपयोग कर सभी फाइलों को सूचीबद्ध करने के लिए मेरी टूटी सिमलिंक एक फ़ाइल के रूप recoganized नहीं कर रहे हैं। क्योंकि मेरा लिंक कुछ भी इंगित नहीं कर रहा है, मैं समझता हूं क्यों।

फिर: मैं कैसे पता लगा सकता हूं कि पर्ल में एक सिम्लिंक टूट गया है या नहीं?

धन्यवाद,

अद्यतन

$ mydir के सभी फ़ाइल सिमलिंक, या तो वैध है या टूट गया है। जब मैं @files I प्रदर्शित करता हूं तो मुझे केवल वैध सिम्लिंक की एक सूची मिलती है।

chdir $dir  or die; 
opendir(DIR, '.') or die; 

foreach my $link (readdir DIR) { 
    next unless -l $link and not -e readlink($link); 

    print "Removing broken link $link\n"; 
    unlink $link; 
} 

closedir DIR; 

ध्यान दें कि यह महत्वपूर्ण है कि निर्देशिका लिंक होता है वर्तमान निर्देशिका है:

opendir DIR, $myDir; 
my @files = grep(/$regexp/,readdir(DIR)); 
closedir DIR; 
print "filenames : @files\n"; 
+0

आपका क्या मतलब है "एक फ़ाइल के रूप recoganized नहीं कर रहे हैं?" किस से? अपना कोड दिखाएं – ysth

उत्तर

8

दो मुख्य प्रासंगिक सिस्टम कॉल कर रहे हैं, stat() and lstat()lstat() कॉल आपको बताएगा कि यह एक सिम्लिंक है (लेकिन अन्य फ़ाइलों पर, stat() जैसा ही व्यवहार करता है)। यह आपको यह निर्धारित करने की अनुमति देता है कि नाम एक सिम्लिंक है। stat() सिस्टम कॉल इसके अंत में एक सिम्लिंक का पालन करता है, और आपको लिंक के अंत में फ़ाइल (या निर्देशिका) के बारे में बताता है। यदि stat() कॉल symlink पर विफल रहता है, तो symlink टूटा हुआ है या आप किसी निर्देशिका या फ़ाइल तक पहुंचने का प्रयास कर रहे हैं जहां आपके पास अनुमति नहीं है।

पर्ल file test ऑपरेटरों में यह पता लगाने के लिए -l शामिल है कि कोई नाम सिमलिंक है या नहीं। आप पर्ल फ़ंक्शन stat और lstat स्पष्ट रूप से उपयोग कर सकते हैं। इनके बीच, आपको यह पता लगाने में सक्षम होना चाहिए कि सिमलिंक टूटा हुआ है या नहीं - लेकिन आपको शायद नौकरी करने के लिए एक फ़ंक्शन लिखने की योजना बनाना चाहिए।

आप शायद readlink पर्ल समारोह उपयोग करने की आवश्यकता नहीं है। अंतर्निहित प्रणाली से सावधान रहें readlink() कॉल; यह एक शून्य-समाप्त स्ट्रिंग वापस नहीं करता है!

यह है कि न तो पर्ल और न ही अपनी POSIX मॉड्यूल realpath() समारोह का समर्थन करता है दिलचस्प है। हालांकि, PathTools मॉड्यूल इसका समर्थन करता है। यदि realpath एक सिम्लिंक पर विफल रहता है, तो सिम्लिंक गैर-कार्यात्मक (उर्फ टूटा हुआ) होता है।

+0

सभी उत्तरों महान थे। मैं सिर्फ स्पष्टीकरण के लिए इसे मान्य करता हूं। धन्यवाद। – Spredzy

4

यहाँ कुछ कोड मैं टूटी कड़ियों निकालने के लिए किया गया है। readdir केवल फ़ाइल नाम देता है, और लिंक सापेक्ष हो सकते हैं। टूटी हुई सिमलिंक (केवल शीर्ष स्तर की जाँच अगर कोई सिमलिंक के लिए सिमलिंक कर रहे हैं) के लिए

+1

+1: नामों की सापेक्षता के बारे में अच्छा बिंदु। आप निर्देशिका के नाम (रिश्तेदार या पूर्ण) में 'readdir' से मान जोड़ सकते हैं और उस से कार्य कर सकते हैं:' अगली जब तक- "$ dir/$ link" और नहीं "$ dir/$ link" '। मैंने उस रीराइट में 'रीडलिंक' छोड़ा; मुझे लगता है कि यह ठीक है क्योंकि ओ/एस आपके लिए लिंक पढ़ता है। –

+0

+1 नामों की सापेक्षता के लिए @ जोनाथन लेफियर के समान ही! – Spredzy

3

की जांच:

use strict; 
use warnings; 
use autodie; 
opendir my $dirh, '.'; 
while (my $file = readdir $dirh) { 
    if (-l $file) { 
     my $target = readlink $file; 
     if (! -e $target && ! -l $target) { 
      print "$file -> $target broken\n"; 
     } 
    } 
} 
2

उपयोग readlink() और stat() परिणाम।

6

stat साथ संयोजन lstat:

say "dangling link at $fn" if (lstat $fn and not stat $fn); 

अद्यतन: यह मेरे लिए काम करता ...

[email protected]:~/t/dl$ perl -E 'opendir $dh, "."; say $_ for grep { !stat $_ and lstat $_ } readdir $dh' 
foo 
[email protected]:~/t/dl$ ls -l 
total 0 
-rw-rw-r-- 1 salva salva 0 2011-07-05 12:34 f 
lrwxrwxrwx 1 salva salva 11 2011-07-05 12:00 fii -> /etc/shadow 
lrwxrwxrwx 1 salva salva 12 2011-07-05 11:59 foo -> /etc/hjdkshf 
1

का उपयोग में निर्मित पर्ल ग्लोब समारोह? उदाहरण के लिए:

@files = <*>; 
foreach $file (@files) { 
    print $file . "\n"; 
} 

एक विशिष्ट $dir के लिए:

@files = <$dir*>; 
foreach $file (@files) { 
    print $file . "\n"; 
}