जवाबों:
इसका कारण यह है कि केवल 1 उत्तर नहीं है ...
shell कमांड लाइन का विस्तारxargs समर्पित उपकरणwhile read कुछ टिप्पणियों के साथwhile read -uइंटरैक्टिव प्रोसेसिंग (नमूना) के fdलिए समर्पित का उपयोग करनाओपी अनुरोध के बारे में: फ़ाइल में सूचीबद्ध सभी लक्ष्यों पर चलनाchmod , xargsसंकेतित उपकरण है। लेकिन कुछ अन्य अनुप्रयोगों के लिए, फ़ाइलों की छोटी मात्रा, आदि ...
यदि आपकी फ़ाइल बहुत बड़ी नहीं है और सभी फाइलें अच्छी तरह से नामित हैं (बिना रिक्त स्थान या अन्य विशेष वर्ण जैसे उद्धरण), तो आप shellकमांड लाइन विस्तार का उपयोग कर सकते हैं । सीधे शब्दों में:
chmod 755 $(<file.txt)
छोटी मात्रा में फ़ाइलों (लाइनों) के लिए, यह कमांड हल्का है।
xargs सही उपकरण हैबड़ी मात्रा में फ़ाइलों के लिए, या आपकी इनपुट फ़ाइल की लगभग किसी भी संख्या में ...
कई लोगों के लिए binutils उपकरण, जैसे chown, chmod, rm, cp -t...
xargs chmod 755 <file.txt
यदि आपके पास विशेष आकर्षण और / या बहुत सारी लाइनें हैं file.txt।
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
यदि आपके आदेश को प्रविष्टि द्वारा ठीक 1 बार चलाने की आवश्यकता है:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
इस नमूने के लिए इसकी आवश्यकता नहीं है, chmodक्योंकि तर्क के रूप में कई फ़ाइलों को स्वीकार करते हैं, लेकिन यह प्रश्न के शीर्षक से मेल खाता है।
कुछ विशेष मामलों के लिए, आप द्वारा उत्पन्न कमांड में फ़ाइल तर्क के स्थान को भी परिभाषित कर सकते हैं xargs:
xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
seq 1 5इनपुट के रूप में परीक्षण करेंइसे इस्तेमाल करे:
xargs -n 1 -I{} echo Blah {} blabla {}.. < <(seq 1 5)
Blah 1 blabla 1..
Blah 2 blabla 2..
Blah 3 blabla 3..
Blah 4 blabla 4..
Blah 5 blabla 5..
जहां प्रति पंक्ति एक बार कमांड किया जाता है ।
while read और वेरिएंट।जैसा कि ओपी सुझाव cat file.txt | while read in; do chmod 755 "$in"; doneकाम करेगा, लेकिन 2 मुद्दे हैं:
cat |एक बेकार कांटा है , और
| while ... ;doneएक उप-क्षेत्र बन जाएगा जहां पर्यावरण के बाद गायब हो जाएगा ;done।
तो यह बेहतर लिखा जा सकता है:
while read in; do chmod 755 "$in"; done < file.txt
परंतु,
आपको झंडे $IFSऔर चेतावनी दी जा सकती है read:
help read
read: read [-r] ... [-d delim] ... [name ...] ... Reads a single line from the standard input... The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on... Only the characters found in $IFS are recognized as word delimiters. ... Options: ... -d delim continue until the first character of DELIM is read, rather than newline ... -r do not allow backslashes to escape any characters ... Exit Status: The return code is zero, unless end-of-file is encountered...
कुछ मामलों में, आपको उपयोग करने की आवश्यकता हो सकती है
while IFS= read -r in;do chmod 755 "$in";done <file.txt
अजनबियों फ़ाइल नाम के साथ समस्याओं से बचने के लिए। और हो सकता है कि यदि आप समस्याओं के साथ संलग्न करें UTF-8:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txtजब आप STDINपढ़ने के लिए उपयोग करते हैं file.txt, तो आपकी स्क्रिप्ट इंटरैक्टिव नहीं हो सकती है (आप STDINअब उपयोग नहीं कर सकते हैं)।
while read -u, समर्पित का उपयोग कर fd।सिंटेक्स: while read ...;done <file.txtरीडायरेक्ट करेगा STDINकरने के लिए file.txt। इसका मतलब है, आप प्रक्रिया से निपटने में सक्षम नहीं होंगे, जब तक कि वे खत्म नहीं हो जाते।
यदि आप इंटरेक्टिव टूल बनाने की योजना बनाते हैं , तो आपको STDINकुछ वैकल्पिक फ़ाइल डिस्क्रिप्टर के उपयोग और उपयोग से बचना होगा ।
स्थिरांक फ़ाइल वर्णनकर्ता हैं: 0के लिए STDIN , 1के लिए STDOUT और 2के लिए STDERR । आप उन्हें देख सकते हैं:
ls -l /dev/fd/
या
ls -l /proc/self/fd/
वहाँ से, आप, अप्रयुक्त संख्या चुन के बीच करने के लिए है 0और 63(अधिक, वास्तव में, के आधार पर sysctlसुपर उपयोगकर्ता उपकरण) के रूप में फ़ाइल वर्णनकर्ता :
इस डेमो के लिए, मैं fd का उपयोग करूंगा 7:
exec 7<file.txt # Without spaces between `7` and `<`!
ls -l /dev/fd/
तब आप read -u 7इस तरह से उपयोग कर सकते हैं :
while read -u 7 filename;do
ans=;while [ -z "$ans" ];do
read -p "Process file '$filename' (y/n)? " -sn1 foo
[ "$foo" ]&& [ -z "${foo/[yn]}" ]&& ans=$foo || echo '??'
done
if [ "$ans" = "y" ] ;then
echo Yes
echo "Processing '$filename'."
else
echo No
fi
done 7<file.txt
done
बंद करने के लिए fd/7:
exec 7<&- # This will close file descriptor 7.
ls -l /dev/fd/
नोटा: मैंने स्ट्राइक किया संस्करण क्योंकि यह वाक्यविन्यास उपयोगी हो सकता है, जब समानताएं प्रक्रिया के साथ कई I / O करते हैं:
mkfifo sshfifo
exec 7> >(ssh -t user@host sh >sshfifo)
exec 6<sshfifocat file.txt | tr \\n \\0 | xargs -0 -n1 chmod 755
tr \\n \\0 <file.txt |xargs -0 [command]आपके द्वारा बताई गई विधि की तुलना में लगभग 50% तेज है।
हाँ।
while read in; do chmod 755 "$in"; done < file.txt
इस तरह आप एक catप्रक्रिया से बच सकते हैं ।
catइस तरह के उद्देश्य के लिए लगभग हमेशा बुरा होता है। आप बिल्ली के बेकार उपयोग के बारे में अधिक पढ़ सकते हैं ।
cat एक अच्छा विचार है, लेकिन इस मामले में, संकेत आदेश हैxargs
chmod(यानी फ़ाइल में प्रत्येक पंक्ति के लिए वास्तव में एक कमांड चलाते हैं)।
read -rमानक इनपुट से एक पंक्ति पढ़ता है ( readबिना -rव्याख्या बैकस्लैश, आपको लगता है कि नहीं करना चाहती)।"
यदि आपके पास एक अच्छा चयनकर्ता है (उदाहरण के लिए एक dir में सभी .txt फ़ाइलें) आप कर सकते हैं:
for i in *.txt; do chmod 755 "$i"; done
या तुम्हारा एक प्रकार:
while read line; do chmod 755 "$line"; done <file.txt
यदि आप जानते हैं कि आपके पास इनपुट में कोई व्हाट्सएप नहीं है:
xargs chmod 755 < file.txt
यदि रास्तों में व्हाट्सएप हो सकता है, और यदि आपके पास GNU xargs है:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
xargsमजबूत है। यह उपकरण बहुत पुराना है और उसके कोड का जोरदार पुनरीक्षण किया गया है । उनका लक्ष्य शेल सीमाओं (64kchar / लाइन या ऐसा कुछ) के संबंध में लाइनें बनाने के लिए प्रारंभिक था। अब यह उपकरण बहुत बड़ी फ़ाइलों के साथ काम कर सकता है और बहुत से कांटे को अंतिम कमांड तक कम कर सकता है। मेरा उत्तर देखें और / या man xargs।
brew install findutils) का उपयोग करके macOS पर GNU xargs स्थापित कर सकते हैं , और फिर gxargsइसके बजाय GNU xargs आह्वान कर सकते हैं , जैसेgxargs chmod 755 < file.txt
यदि आप प्रत्येक पंक्ति के समानांतर अपनी कमांड चलाना चाहते हैं तो आप GNU समानांतर का उपयोग कर सकते हैं
parallel -a <your file> <program>
आपकी फ़ाइल की प्रत्येक पंक्ति को तर्क के रूप में प्रोग्राम करने के लिए पास किया जाएगा। डिफ़ॉल्ट parallelरूप से आपके CPU गिनती के रूप में कई धागे चलाता है। लेकिन आप इसे निर्दिष्ट कर सकते हैं-j
मैं देखता हूं कि आपने बैश को टैग किया है, लेकिन पर्ल भी ऐसा करने का एक अच्छा तरीका होगा:
perl -p -e '`chmod 755 $_`' file.txt
आप यह सुनिश्चित करने के लिए कि आप सही फ़ाइलें प्राप्त कर रहे हैं, उदाहरण के लिए केवल .txt फ़ाइलों को संसाधित करने के लिए एक regex भी लागू कर सकते हैं:
perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt
"पूर्वावलोकन" करने के लिए, क्या हो रहा है, बस बैकटिक्स को दोहरे उद्धरण चिह्नों के साथ बदलें print:
perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
chmodकार्य है
perl -lpe 'chmod 0755, $_' file.txt- -l"ऑटो-
आप AWK का भी उपयोग कर सकते हैं जो आपको फ़ाइल को संभालने के लिए अधिक लचीलापन दे सकता है
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
यदि आपकी फ़ाइल में फ़ील्ड विभाजक है जैसे:
फ़ील्ड 1, field2, फ़ील्ड 3
केवल पहला क्षेत्र प्राप्त करने के लिए
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
आप GNU दस्तावेज़ीकरण https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple पर अधिक विवरण देख सकते हैं
तर्क कई अन्य उद्देश्यों पर लागू होता है। और कैसे /। / फाइल सिस्टम से प्रत्येक उपयोगकर्ता के .sh_history को पढ़ने के लिए? क्या होगा अगर उनमें से हजार हैं?
#!/bin/ksh
last |head -10|awk '{print $1}'|
while IFS= read -r line
do
su - "$line" -c 'tail .sh_history'
done
यहाँ स्क्रिप्ट https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh है
मुझे पता है कि यह देर हो चुकी है लेकिन अभी भी है
यदि किसी भी संयोग से आप \r\nइसके बजाय विंडोज़ सेव की हुई टेक्स्ट फ़ाइल में चलते हैं \n, तो आप आउटपुट से भ्रमित हो सकते हैं यदि आपके कमांड को पढ़ने के बाद इस तर्क के बाद sth है। तो \rउदाहरण के लिए निकालें :
cat file | tr -d '\r' | xargs -L 1 -i echo do_sth_with_{}_as_line
xargsइस तरह की ज़रूरत का जवाब देने के लिए प्रारंभिक निर्माण किया गया था, कुछ सुविधाएँ, जैसे वर्तमान वातावरणchmodमें यथासंभव कम से कम इस मामले में निवेश करने के लिए कमांड का निर्माण करना, कांटे कम करना प्रभावशीलता सुनिश्चित करता है।while ;do..done <$file1 फ़ाइल के लिए 1 कांटा चल रहा है।xargsएक विश्वसनीय तरीके से हजार फाइलों के लिए 1 कांटा चला सकता है।