जवाबों:
बैश या ksh में, फ़ाइल नामों को किसी सरणी में रखें, और उस सरणी पर उल्टे क्रम में पुनरावृति करें।
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
यदि ksh_arraysविकल्प सेट है (तो यह ksh इम्यूलेशन मोड में है) ऊपर का कोड भी zsh में काम करता है । Zsh में एक सरल विधि है, जो ग्लोब क्वालीफायर के माध्यम से मैचों के क्रम को उल्टा करने के लिए है:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX में सरणियाँ शामिल नहीं हैं, इसलिए यदि आप पोर्टेबल होना चाहते हैं, तो स्ट्रिंग्स की एक सरणी को सीधे स्टोर करने का आपका एकमात्र विकल्प स्थितिगत पैरामीटर है।
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
iऔर f; बस shift, $1अपने कॉल के लिए उपयोग करें bar, और [ -z $1 ]अपने में परीक्षण करें while।
[ -z $1 ]और न ही [ -z "$1" ]उपयोगी परीक्षण हैं (क्या होगा अगर पैरामीटर था *, या एक खाली स्ट्रिंग?)। और किसी भी मामले में वे यहां मदद नहीं करते हैं: सवाल यह है कि विपरीत क्रम में लूप कैसे किया जाए।
जब तक आप पंक्ति को "कायरता वर्ण" नहीं मानते, तब तक यह कोशिश करें:
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
fमेरी स्थिति में परिवर्तनशीलता को तोड़ दिया । यह उत्तर हालांकि, साधारण forलाइन के लिए ड्रॉप-इन प्रतिस्थापन के रूप में बहुत अधिक कार्य करता है ।
यदि कोई यह पता लगाने की कोशिश कर रहा है कि अंतरिक्ष-सीमांकित स्ट्रिंग सूची पर पुनरावृति कैसे करें, तो यह काम करता है:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tacएक हिस्सा है। लेकिन आपका समाधान भी एक अच्छा है।
tac। हालांकि tacयहाँ पर बिना-प्रतिक्रिया के संख्या से मुझे लगता है कि शायद OSX tac नहीं है। जिस स्थिति में @ arp के समाधान के कुछ प्रकार का उपयोग करें - वैसे भी समझना आसान है।
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
आपके इच्छित तरीके को संचालित करना चाहिए (यह मैक ओएस एक्स पर परीक्षण किया गया था और मेरे पास नीचे एक चेतावनी है ...)।
खोजने के लिए आदमी पृष्ठ से:
-print0
This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
असल में, आप उन फ़ाइलों को ढूंढ रहे हैं जो आपके स्ट्रिंग + ग्लोब से मेल खाती हैं और प्रत्येक को NUL वर्ण से समाप्त करती हैं। यदि आपके फ़ाइल नाम में नई लाइनें या अन्य अजीब अक्षर हैं, तो आपको इसे अच्छी तरह से संभालना चाहिए।
tail -r
पाइप के माध्यम से मानक इनपुट लेता है और इसे उलट देता है (ध्यान दें कि सभी इनपुट को स्टडआउट में tail -rप्रिंट करता है, और न केवल अंतिम 10 लाइनें, जो मानक डिफ़ॉल्ट है। man tailअधिक जानकारी के लिए)।
हम फिर उसे पाइप करते हैं xargs -0:
-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the
-print0 function in find(1).
यहाँ, xargs को NUL चरित्र द्वारा अलग किए गए तर्कों को देखने की उम्मीद है, जिन्हें आपने पास किया findऔर उलट दिया tail।
मेरी चेतावनी: मैंने पढ़ा है कि tailअशक्त-समाप्त स्ट्रिंग्स के साथ अच्छा नहीं खेलता । मैक ओएस एक्स पर यह अच्छी तरह से काम करता है, लेकिन मैं गारंटी नहीं दे सकता कि सभी * निक्स के मामले में। सावधानी से चलना।
मुझे यह भी उल्लेख करना चाहिए कि GNU समानांतर का उपयोग अक्सर एक xargsविकल्प के रूप में किया जाता है । आप यह भी देख सकते हैं।
मुझे कुछ याद आ रहा है, इसलिए दूसरों को झंकारना चाहिए।
tail -rहालांकि समर्थन नहीं करता है ... क्या मैं कुछ गलत कर रहा हूं?
tacएक विकल्प के रूप में उल्लेख किया है , इसलिए मैं इसके बजाय कोशिश
tail -rOSX के लिए विशिष्ट है, और न्यूलाइन-सीमांकित इनपुट को उलट देता है, शून्य-सीमांकित इनपुट नहीं। आपका दूसरा समाधान बिल्कुल भी काम नहीं करता (आप इनपुट को पाइप कर रहे हैं ls, जिसकी कोई परवाह नहीं है); कोई आसान तय नहीं है जो इसे मज़बूती से काम करेगा।
आपके उदाहरण में आप कई फ़ाइलों पर लूपिंग कर रहे हैं, लेकिन मुझे यह प्रश्न अपने अधिक सामान्य शीर्षक के कारण मिला, जो किसी सरणी पर लूपिंग को कवर कर सकता है, या किसी भी क्रम के आधार पर उलट सकता है।
यहाँ है कि Zsh में कैसे करें:
यदि आप किसी सरणी में तत्वों पर लूप कर रहे हैं, तो इस सिंटैक्स का उपयोग करें ( स्रोत )
for f in ${(Oa)your_array}; do
...
done
Oअगले झंडे में निर्दिष्ट आदेश के विपरीत; aसामान्य सरणी क्रम है।
जैसा कि @Gilles ने कहा, Onआपकी ग्लॉब्ड फाइल्स को ऑर्डर करेगा, जैसे कि my/file/glob/*(On)। ऐसा इसलिए Onहै क्योंकि "रिवर्स नेम ऑर्डर है।"
Zsh तरह झंडे:
a सरणी क्रमL फ़ाइल की लंबाईl लिंक की संख्याm सुधार की तारीखn नाम^oरिवर्स ऑर्डर ( oसामान्य ऑर्डर है)O उल्टे क्रमउदाहरण के लिए, https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt और http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- देखें टू-गुरु-अपने-Z-खोल /
Mac OSX tacकमांड का समर्थन नहीं करता है । @Tcdyl द्वारा समाधान तब काम करता है जब आप एक कमांड को forलूप में बुला रहे हैं । अन्य सभी मामलों के लिए, इसके चारों ओर जाने का सबसे सरल तरीका निम्नलिखित है।
यह दृष्टिकोण आपके फ़ाइलनाम में नई सूचियाँ होने का समर्थन नहीं करता है। अंतर्निहित कारण यह है कि tail -rइसके इनपुट को न्यूलाइन द्वारा सीमांकित किया गया है।
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
हालांकि, न्यूलाइन सीमा के आसपास जाने का एक तरीका है। यदि आप जानते हैं कि आपके फ़ाइल नाम में एक निश्चित वर्ण नहीं है (कहते हैं, '='), तो आप trइस वर्ण को बनने के लिए सभी नई सूचियों को बदलने के लिए उपयोग कर सकते हैं और फिर छँटाई कर सकते हैं। परिणाम इस प्रकार दिखेगा:
for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done
नोट: आपके संस्करण के आधार पर tr, यह '\0'एक चरित्र के रूप में समर्थन नहीं कर सकता है । यह आमतौर पर सी में स्थान बदलकर सी के आसपास काम किया जा सकता है (लेकिन मुझे याद नहीं है कि वास्तव में कैसे ठीक है, क्योंकि इसे एक बार ठीक करने के बाद अब यह मेरे कंप्यूटर पर काम करता है)। यदि आपको कोई त्रुटि संदेश मिलता है, और आपको वर्कअराउंड नहीं मिल सकता है, तो कृपया इसे टिप्पणी के रूप में पोस्ट करें, इसलिए मैं आपको इसका निवारण करने में मदद कर सकता हूं।
sort -rपहले पाइपfor, या के माध्यम से launderls -r।