$ घर की सामग्री को `watch` क्यों बनाते हैं` ls / tmp` सूची?


13

मैं अपनी /tmp/निर्देशिका में फ़ाइलों की संख्या देखने की कोशिश कर रहा हूं । इसके लिए मुझे लगा कि यह कमांड काम करेगी:

watch sh -c 'ls /tmp/|wc -l'

लेकिन यह काम करने के लिए प्रतीत होता है जैसे कि lsकोई तर्क नहीं था। अर्थात्, मैं अंदर हूं ~, और मुझे इसके बजाय फाइलों की संख्या मिल रही है /tmp/। मुझे एक वर्कअराउंड मिला, जो काम करने लगता है:

watch sh -c 'ls\ /tmp/|wc -l'

लेकिन मुझे lsऔर के बीच की जगह से बचने की आवश्यकता क्यों है /tmp/? कमांड को किस प्रकार से रूपांतरित किया जाता है watchताकि lsआउटपुट को फीड किया जा सके wc, लेकिन /tmp/तर्क के रूप में पारित नहीं किया जाता है ls?


1
watch "sh -c 'ls /tmp | wc -l'"इस आदेश को करने से वांछित प्रभाव प्राप्त होना चाहिए। यह गलती नहीं देखता है, कोशिश करो sh -c ls /tmpऔर आप अपने घर निर्देशिका प्राप्त करेंगे (लेकिन मुझे पता नहीं क्यों ...)
जैकब मिनशॉल

8
उत्तर नहीं, लेकिन आप watchगलत तरीके से उपयोग कर रहे हैं । जिस कमांड को आप पास करते हैं, watchवह इसके द्वारा खिलाया जाता watchहै sh -c, इसलिए आप sh -cदो बार कर रहे हैं ।
19

यदि आप जिज्ञासु हैं, तो आप स्रोत पर भी नज़र डाल सकते हैं ।
माईस

1
@JacobMinshall, सीधा क्यों है: इस मामले में /tmpएक तर्क है sh, एक तर्क नहीं है ls
चार्ल्स डफी

जवाबों:


17

अंतर के माध्यम से देखा जा सकता है strace:

$ strace -ff -o bq watch sh -c 'ls\ /tmp/|wc -l'
^C
$ strace -ff -o nobq watch sh -c 'ls /tmp/|wc -l'
^C
$ grep exec bq* | grep sh
bq.29218:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls\\ /tmp/|wc -l"], [/* 54 vars */]) = 0
bq.29219:execve("/bin/sh", ["sh", "-c", "sh -c ls\\ /tmp/|wc -l"], [/* 56 vars */]) = 0
bq.29220:execve("/bin/sh", ["sh", "-c", "ls /tmp/"], [/* 56 vars */]) = 0
$ grep exec nobq* | grep sh
nobq.29227:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls /tmp/|wc -l"], [/* 54 vars */]) = 0
nobq.29228:execve("/bin/sh", ["sh", "-c", "sh -c ls /tmp/|wc -l"], [/* 56 vars */]) = 0
nobq.29229:execve("/bin/sh", ["sh", "-c", "ls", "/tmp/"], [/* 56 vars */]) = 0

बैककौट मामले में, ls /tmpएकल तर्क के रूप में पारित किया जाता -cहै sh, जो उम्मीद के मुताबिक चलता है। इस बैककवर के बिना, कमांड शब्द विभाजन के बजाय होता है जब watchरन shजो आपूर्ति को चलाता है sh, ताकि केवल lsतर्क के रूप में पारित किया जाता है -c, जिसका अर्थ है कि उप-उप shकेवल एक नंगे lsकमांड चलाएगा , और वर्तमान काम की सामग्री को सूचीबद्ध करेगा। निर्देशिका।

तो, क्यों की जटिलता sh -c ...? बस क्यों नहीं चलती watch 'ls /tmp|wc -l'?


ओह, वास्तव में straceइसे करने की कोशिश करने के बारे में नहीं सोचा था ।
रुस्लान

1
दरअसल, `बैककॉट (या बैक-टिक) है। यह प्रश्न बैकस्लैश के बारे में है।
जी-मैन का कहना है कि 'मोनिका'

@Ruslan: मैंने यह टिप्पणी इस उत्तर पर पोस्ट की है क्योंकि यह इस उत्तर पर टिप्पणी है । thrig कहते हैं, "में backquote मामला है, ls /tmpहै ..." और "यह बिना backquote , आदेश है ...", और का उपयोग करता है bqऔर nobqफ़ाइल नाम, के रूप में जब यह सब करते हुए की चर्चा करते हुए बैकस्लैश अपने में ls\ /tmpआदेश।
जी-मैन का कहना है कि 'मोनिका'

8

watchआदेशों की दो मुख्य श्रेणियां हैं (उनमें से जो समय-समय पर कमांड चलाने के लिए हैं, watchएक मानक कमांड नहीं है, यहां तक ​​कि सिस्टम भी हैं जहां watchकुछ पूरी तरह से अलग होता है जैसे फ्रीबीएसडी पर एक और ट्टी लाइन पर स्नूपिंग)।

एक जो पहले से ही एक शेल में रिक्त स्थान के साथ अपने तर्कों के संघटन को पारित करता है (यह प्रभाव कॉल में होता है sh -c <concatenation-of-arguments>) और एक जो केवल शेल को लागू किए बिना निर्दिष्ट तर्कों के साथ निर्दिष्ट कमांड चलाता है।

आप पहली स्थिति में हैं, इसलिए आपको बस जरूरत है:

watch 'ls /tmp/|wc -l'

जब तुम करोगे:

watch sh -c 'ls /tmp/|wc -l'

आपका watchवास्तव में चलता है:

sh -c 'sh -c ls /tmp/|wc -l'

और इनलाइन स्क्रिप्ट sh -c ls /tmp/चला रहा है, lsजहां $0है /tmp/(इसलिए lsबिना तर्क के चलाया जाता है और वर्तमान निर्देशिका को सूचीबद्ध करता है)।

watchपहली श्रेणी में कुछ कार्यान्वयन (जैसे कि लिनक्स पर procps- एनजी से एक) -xउन्हें watchदूसरी श्रेणी की तरह व्यवहार करने के लिए एक विकल्प स्वीकार करते हैं । तो वहाँ के साथ, आप कर सकते हैं:

watch -x sh -c 'ls /tmp/|wc -l'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.