मैं दो bash कमांड का उपयोग कैसे कर सकता हूँ-कमांड खोजने में?


32

क्या कमांड के -execहिस्से में 2 कमांड का उपयोग करना संभव है find?

मैंने कुछ इस तरह की कोशिश की है:

find . -name "*" -exec  chgrp -v new_group {}  ; chmod -v 770 {}  \;

और मुझे मिलता है:

खोज: गायब तर्क -exec
chmod: पहुँच नहीं सकता {}: ऐसी कोई फ़ाइल या निर्देशिका
chmod: पहुँच नहीं सकता ;: ऐसी कोई फ़ाइल या निर्देशिका नहीं

जवाबों:


44

के रूप में findआदेश, आप भी सिर्फ और जोड़ सकते हैं -execआदेशों एक पंक्ति में:

find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;

ध्यान दें कि यह कमांड, इसके परिणाम में, उपयोग करने के बराबर है

chgrp -v new_group file && chmod -v 770 फ़ाइल

प्रत्येक फ़ाइल पर।

सभी findतरह के रूप में की मानकों -name, -exec, -sizeऔर इतने पर, वास्तव में कर रहे परीक्षण : findलंबे समय के रूप एक एक करके उन्हें एक के रूप में चलाने के लिए पूरी श्रृंखला अब तक के लिए मूल्यांकन किया गया है जारी रहेगा सच । इसलिए प्रत्येक लगातार -execआदेश केवल तभी निष्पादित किया जाता है जब पिछले वाले सही हो गए (यानी 0कमांडों की निकास स्थिति)। लेकिन findयह भी इस तरह के रूप तर्क ऑपरेटरों को समझता है या ( -o) और नहीं ( !)। इसलिए, पिछले परिणामों की परवाह किए बिना-exec परीक्षणों की एक श्रृंखला का उपयोग करने के लिए , किसी को इस तरह से कुछ का उपयोग करने की आवश्यकता होगी:

find . -name "*" \( -exec chgrp -v new_group {} \; -o -exec chmod -v 770 {} \; \)

4
+1: हाँ, यह करने का सबसे सुंदर तरीका है। यदि आप समझा सकते हैं, तो आप क्यों उपयोग करते हैं '{}'(ब्रेसिज़ के चारों ओर एपोस्ट्रोफ़्स), कृपया देखें: unix.stackexchange.com/q/8647/4485
उपयोगकर्ता अज्ञात

1
@user दुर्भाग्य से, मुझे नहीं पता कि क्या यह अभी भी आवश्यक है। मैंने अभी कुछ परीक्षण किया और ऐसी स्थिति में नहीं आया जहां यह कुछ भी बदले। मुझे लगता है कि यह सिर्फ "अच्छा अभ्यास" है जो मर जाएगा।
rozcietrzewiacz

2
उनके नाम में रिक्त स्थान वाली फ़ाइलों के लिए उद्धरण महत्वपूर्ण हैं।
naught101

17
find . -name "*" -exec sh -c 'chgrp -v new_group "$0" ; chmod -v 770 "$0"' {} \;

@ गिल्स: -c$ 0 के अजीब हैंडलिंग के चमत्कार मुझे लगता है कि हर बार जब मैं इसे देखता हूं तो यह गलत है, लेकिन यह निश्चित रूप से सही है।
derobert

मुझे स्पष्ट शेल परिभाषित किया जा रहा है ...
djangofan

यह उत्तर (और जाइल्स का उत्तर) दिए गए प्रश्न के बेहतर उत्तर की तरह लगता है sh -c

14

आपकी कमांड पहले शेल द्वारा दो कमांडों द्वारा अलग की गई है ;, जो एक नई रेखा के बराबर है:

find . -name "*" -exec chgrp -v new_group {}
chmod -v 770 {} \;

यदि आप एक शेल कमांड चलाना चाहते हैं, तो एक शेल को स्पष्ट रूप से संलग्न करें bash -c(या sh -cयदि आपको परवाह नहीं है कि शेल विशेष रूप से बैश है):

find . -name "*" -exec sh -c 'chgrp -v new_group "$0"; chmod -v 770 "$0"' {} \;

{}शेल के तर्क के रूप में उपयोग पर ध्यान दें ; यह शून्य तर्क है (जो आमतौर पर शेल या स्क्रिप्ट का नाम है, लेकिन यह यहां कोई फर्क नहीं पड़ता), इसलिए इसे संदर्भित किया जाता है "$0"

आप एक बार में शेल में कई फ़ाइल नाम पास कर सकते हैं और शेल को उनके माध्यम से पुनरावृत्त कर सकते हैं, यह तेज़ हो जाएगा। यहां मैं _स्क्रिप्ट नाम के रूप में पास करता हूं और निम्नलिखित तर्क फ़ाइल नाम हैं, जो for x(के लिए एक शॉर्टकट for x in "$@") से अधिक पुनरावृत्त करता है।

find . -name "*" -exec sh -c 'for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done' _ {} +

ध्यान दें कि बैश 4 के बाद से, या zsh में, आपको यहां बिल्कुल भी खोजने की आवश्यकता नहीं है। बैश में, एक पुनरावर्ती निर्देशिका ग्लोब के लिए खड़े होने को सक्रिय करने के लिए चलाएं shopt -s globstar(इसे अपने में डालें ~/.bashrc) **/। (Zsh में, यह हर समय सक्रिय है।) फिर

chgrp -v new_group -- **/*; chmod -v 770 -- **/*

या यदि आप चाहते हैं कि फाइलों को क्रम में पुनरावृत्त किया जाए

for x in **/*; do
  chgrp -v new_group -- "$x"
  chmod -v 770 -- "$x"
done

findकमांड के साथ एक अंतर यह है कि शेल डॉट फाइल्स (जिन फाइलों का नाम ए से शुरू होता है .) को अनदेखा करता है । उन्हें शामिल करने के लिए, बैश में, पहले सेट GLOBIGNORE=.:..; zsh में, **/*(D)ग्लोब पैटर्न के रूप में उपयोग करें ।


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