सिम्लिंक से एक नियमित फ़ाइल को भेद करना


22

मैं एक बैश स्क्रिप्ट लिख रहा हूं, जिसमें एक नियमित फाइल को एक सिमलिंक से अलग करने की आवश्यकता है। मुझे लगा कि मैं ऐसा कर सकता / सकती हूं, यदि मैं अभिव्यक्ति की जांच / परीक्षण करूं, लेकिन यह उस तरह से काम नहीं करता जैसा कि मुझे उम्मीद थी:

$ touch regular_file
$ test -f regular_file; echo $?
0
$ test -h regular_file; echo $?
1
$ ln -s regular_file symlink
$ test -h symlink; echo $?
0
$ test -f symlink; echo $?
0

ऐसा क्यों है? और, मैं यह कैसे ठीक से कर सकता हूं?

जवाबों:


20

ऐसा लगता है कि आप बस अपने परीक्षणों को थोड़ा बढ़ा रहे हैं। आपको दोनों परीक्षण चलाने की आवश्यकता नहीं है, इस मामले के लिए आपको केवल वही चाहिए जो आपको यह -hबताने के लिए हो कि फ़ाइल एक सिमलिंक है या नहीं।

test -h file && echo "is symlink" || echo "is regular file"

-fपरीक्षण केवल आपको बताता है कि वस्तु एक फाइल है। यह वापसी होगी 0अगर यह एक निर्देशिका या एक युक्ति नोड या निर्देशिका में एक सिमलिंक था, लेकिन वापस आ जाएगी 1फाइल में एक सिमलिंक पर।

यदि आपको यह जानना भी आवश्यक है कि क्या यह निर्देशिका की बजाय किसी फ़ाइल के लिए सिम्लिंक था, तो आपको दोनों परीक्षणों के परिणामों को थोड़े से तर्क के साथ संयोजित करना होगा।


मैं डॉक्स से समझ में आ के रूप में, के बीच का अंतर -eऔर -fहै कि गया था -eअगर (किसी भी प्रकार की) एक फ़ाइल अस्तित्व में पता करने के लिए इस्तेमाल किया गया था, और -fपरीक्षण करने के लिए विशेष रूप से किया गया है, तो फ़ाइल अस्तित्व में है और एक नियमित रूप से फ़ाइल था। ऐसा लगता है कि मुझे गलत समझ में आया कि एक "नियमित फ़ाइल" क्या थी
Nupraptor

1
@ अनुप्रेषक: हाँ, आपने डॉक्स को गलत समझा। एक सिम्लिंक को एक नियमित फ़ाइल माना जाता है, जो एक अन्य प्रकार के नोड्स के विपरीत होती है जो एक फ़ाइल (ब्लॉक-डिवाइस नोड, चरित्र-डिवाइस नोड, निर्देशिका, आदि) हो सकती है। यदि आप यह जानना चाहते हैं कि यह किस प्रकार की फाइल है, तो आपको फाइल टाइप विशिष्ट परीक्षण चलाना होगा -h, जैसे कि सिम्बलिंक के लिए, -pनामित पाइप के लिए, आदि
कालेब

फिर, मैं कैसे परीक्षण करूं कि कोई फ़ाइल उस अर्थ में एक नियमित फ़ाइल है जो न तो पाइप है और न ही सिमलिंक, आदि? क्या मुझे इसके लिए एक और सवाल खोलना चाहिए?
नूप्रेपटोर

@Nupraptor: एकमात्र अजीब मामला एक सिम्लिंक है जो एक नियमित फ़ाइल से जुड़ता है। अन्यथा, यदि यह एक नियमित फ़ाइल के रूप में परीक्षण करता है, तो यह एक नियमित फ़ाइल है।
डेविड श्वार्ट्ज

3
परीक्षण -f निर्देशिका एक 1 नहीं 0: परीक्षण -f लौटेगी। ; इको $? (आउटपुट 1)
बहुपद

7

@Caleb स्क्रिप्ट को सिम्लिंक के लिए परीक्षण करने के बारे में सही है। हालाँकि इसके बारे में क्यों छोड़ दिया गया था और मैं उत्सुक था। यदि आप कोरुटिल्स स्रोत कोड को देखते हैं और परीक्षण के आउटपुट को स्ट्रेस करते हैं, तो आप देख सकते हैं कि जब आप प्रतीकात्मक लिंक परीक्षण चलाते हैं तो यह lstat का उपयोग करता है और यदि आप -f परीक्षण का उपयोग करते हैं तो यह वास्तव में 'स्टेट' कहलाता है जो सिम्लिंक का अनुसरण करता है:

$ ln -s varnish_config XXX
$ strace -s 2000 test -L XXX 2>&1 | grep XXX
execve("/usr/bin/test", ["test", "-L", "XXX"], [/* 47 vars */]) = 0
lstat("XXX", {st_mode=S_IFLNK|0777, st_size=14, ...}) = 0

$ strace -s 2000 test -L varnish_config 2>&1 | grep varnish
execve("/usr/bin/test", ["test", "-L", "varnish_config"], [/* 47 vars */]) = 0
lstat("varnish_config", {st_mode=S_IFREG|0664, st_size=1046, ...}) = 0

$ strace -s 2000 test -f XXX 2>&1 | grep XXX
execve("/usr/bin/test", ["test", "-f", "XXX"], [/* 47 vars */]) = 0
stat("XXX", {st_mode=S_IFREG|0664, st_size=1046, ...}) = 0

स्टेट मैन पेज से:

   stat() stats the file pointed to by path and fills in buf.

   lstat() is identical to stat(), except that if path is a symbolic link,
   then the link itself is stat-ed, not the file that it refers to.

इसका मतलब है कि -f परीक्षण तब तक सही होगा जब तक निर्दिष्ट फ़ाइलनाम एक नियमित फ़ाइल या एक नियमित फ़ाइल के लिए एक सिमलिंक है।

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