2013-02-22 26 views
5

मैं एक साधारण बैश for पाश बनाकर सभी सबडायरेक्टरियों की अनुमतियां परिवर्तित करने की कोशिश कर रहा हूँ है:खोज परिणामों का उपयोग करना जब निर्देशिका उनके नाम में रिक्त स्थान

for dir in `find . -type d`; do chmod 755 "$dir"; done 

तथापि, यह गैर-मौजूद निर्देशिका के बारे में शिकायत। लूप से निर्देशिका नामों को प्रिंट करके (chmod 755 "$dir" को echo "$dir" के साथ बदलकर) मैंने काम किया है कि समस्या तब होती है जब किसी निर्देशिका में उसके नाम पर रिक्त स्थान होता है। क्या होता है कि for पाश find के प्रत्येक न्यूलाइन और स्थान पर परिणामों को विभाजित करता है।

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

उत्तर

6

इस समस्या का हमेशा की तरह समाधान है:

find ... -print0 | xargs -0 ... 

-print0 तर्क उत्पादन फ़ाइल नामों का कारण बनता है नल-टर्मिनेटेड होने के लिए और -0/-null xargs के लिए तर्क इस तरह के प्रारूप को पढ़ने के लिए कहता है।

अपने मामले में

तो ...

$ find . -type d -a -print0 | xargs -0 chmod 755 

आप वास्तव में खोल पाश बिल्कुल जरूरत नहीं है।

+0

ठीक है, यह वाकई अच्छा है :)। लेकिन तर्कों की सूची बहुत लंबी है, लेकिन मैंने कुछ आदेशों को घबराहट देखा है। क्या ऐसा कुछ है जिसे xargs -n पैरामीटर का उपयोग करके हल किया जा सकता है? –

+0

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

+1

तर्कों की # पर सीमा आमतौर पर कर्नेल की निष्पादन सीमा होती है, जो * xargs * चेक करता है और एक से अधिक बार कमांड चलाकर स्वचालित रूप से संभालता है। यह एक कमांड को भी संभाल सकता है जो वास्तव में केवल 1 की अनुमति देता है, उपयोग करें: * xargs -n 1 * – DigitalRoss

1

बजाय यह करके देखें (builtins का उपयोग कर, की आवश्यकता है bash --version> = 4):

shopt -s globstar 
for dir in **/*/; do 
    chmod 0755 "${dir%/}" 
done 
+2

ध्यान दें कि इसके लिए 'bash' 4 या बाद की आवश्यकता है। – chepner

4

यहां आपके टूलकिट के लिए कुछ और विकल्प हैं। तुम सिर्फ फ़ाइलें/निर्देशिका के समूहों पर अमल करने के लिए एक भी आदेश है, तो find यह सीधे कर सकते हैं:

find . -type d -exec chmod 755 {} + 

आदेश केवल एक समय में एक फ़ाइल/निर्देशिका पर काम कर सकते हैं, तो करने के लिए + के बजाय \; का उपयोग प्रत्येक आइटम के लिए एक बार चलाएँ:

find . -type d -exec chmod 755 {} \; 

और अगर आप कुछ जटिल (यानी कई आदेशों) क्या करने की जरूरत है, तो आप पाश का एक सुरक्षित संस्करण बना सकते हैं:

while IFS= read -r -u3 -d $'\0' dir; do 
    sudo chown gkudelis "$dir" 
    chmod 755 "$dir" 
    touch "$dir/.perms_reset" 
done 3< <(find /tmp -type f -print0) 

ध्यान दें कि यह एक पाइप के बजाय एक प्रक्रिया प्रतिस्थापन (<(...)) से एक रीडायरेक्ट का उपयोग करता है ताकि सबशेल में लूप चलाने से बचें; यह एक बैश-केवल सुविधा है, इसलिए आपको #!/bin/bash के साथ स्क्रिप्ट शुरू करना होगा, #!/bin/sh नहीं। साथ ही, यह stdin के बजाय fd 3 पर रीडायरेक्ट करता है, इसलिए यदि लूप के अंदर कुछ भी stdin से पढ़ने की कोशिश करता है तो यह भ्रमित नहीं होगा। साथ ही, इसमें रिक्त स्थान की सुरक्षा के लिए लूप वैरिएबल ("$dir") के सभी संदर्भों के चारों ओर डबल-कोट्स का उपयोग करना सुनिश्चित करें। अधिक जानकारी के लिए BashFAQ #020 देखें।

+0

स्वीकार किए गए एक से अधिक उपयोगी उत्तर, क्योंकि यह बड़ी संख्या में समस्या के लिए काम करता है। –