फ़ाइल डिस्क्रिप्टर और शेल स्क्रिप्टिंग


32

मुझे यह समझने में बहुत मुश्किल समय हो रहा है कि कोई शेल स्क्रिप्ट में फ़ाइल डिस्क्रिप्टर का उपयोग कैसे करता है।

मैं मूल बातें जानता हूं जैसे कि

exec 5 > /tmp/foo

तो fd 5 लिखने के लिए foo से जुड़ा हुआ है।

exec 6 < /tmp/bar

… पढ़ने के लिए।

exec 5>&-

... करीब एफडी।

अब यह क्या करता है?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

जैसा कि मैं समझता हूं &5कि एफडी को बंद कर दिया गया है, इसलिए प्रत्येक कॉल के बाद भी आउटपुट को फिर से सफलतापूर्वक कैसे निर्देशित किया जा रहा है?

यह एक कॉपी पास्ता है: यहाँ

यह दावा करता है कि इसे एक साधारण से अधिक उपयोग करने से echo $a > fileयह बहुत जल्दी हो जाएगा, लेकिन मैं समझने में विफल रहता हूं। मैं सभ्य ट्यूटोरियल के किसी भी लिंक की सराहना करूंगा। मुझे लगता है कि Google शक्तियां मुझे विफल कर रही हैं।

जवाबों:


44

सबसे पहले, ध्यान दें कि बंद करने के लिए सिंटैक्स है 5>&-या 6<&-, इस पर निर्भर करता है कि फाइल डिस्क्रिप्टर लिखने के लिए पढ़ा जा रहा है या पढ़ने के लिए। उस ब्लॉग पोस्ट में एक टाइपो या स्वरूपण गड़बड़ प्रतीत होती है।

यहाँ टिप्पणी लिपि है।

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

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

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

जब आप बदले में कई फ़ाइलों को लिखना चाहते हैं, तो स्पष्ट फ़ाइल डिस्क्रिप्टर का उपयोग करना उपयोगी हो जाता है। उदाहरण के लिए, उस स्क्रिप्ट पर विचार करें जो डेटा आउटपुट फ़ाइल में डेटा आउटपुट करती है और लॉग फ़ाइल में डेटा लॉगिंग करती है और संभवतः त्रुटि संदेश भी। इसका मतलब है कि तीन आउटपुट चैनल: एक डेटा के लिए, एक लॉग के लिए और एक त्रुटियों के लिए। चूंकि आउटपुट के लिए केवल दो मानक विवरण हैं, एक तीसरे की आवश्यकता है। आप execआउटपुट फाइल खोलने के लिए कॉल कर सकते हैं :

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3

if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

दक्षता के बारे में टिप्पणी तब आती है जब आप एक लूप में पुनर्निर्देशन करते हैं, इस तरह (मान लें कि फ़ाइल को शुरू करने के लिए खाली है):

while …; do echo $a >>/tmp/bar; done

प्रत्येक पुनरावृत्ति पर, प्रोग्राम खुलता है /tmp/bar, फ़ाइल के अंत की तलाश करता है, कुछ डेटा जोड़ता है और फ़ाइल को बंद कर देता है। फ़ाइल को एक बार और सभी के लिए खोलना अधिक कुशल है:

while …; do echo $a; done >/tmp/bar

जब अलग-अलग समय पर कई पुनर्निर्देशन हो रहे हैं, तो execपुनर्निर्देशन में ब्लॉक को लपेटने के बजाय पुनर्निर्देशन करने के लिए कॉल करना उपयोगी हो जाता है।

exec >/tmp/bar
while …; do echo $a; done

आपको इस साइट पर टैग ब्राउज़ करके पुनर्निर्देशन केio-redirection कई अन्य उदाहरण मिलेंगे ।


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