मैं एक निर्देशिका को लॉग करने योग्य फ़ाइलों से भरा रखने की कोशिश कर रहा हूं। रात भर, मैं सभी को हटाना चाहता हूं लेकिन 10 सबसे हाल ही में। मैं इसे एक कमांड में कैसे कर सकता हूं?
मैं एक निर्देशिका को लॉग करने योग्य फ़ाइलों से भरा रखने की कोशिश कर रहा हूं। रात भर, मैं सभी को हटाना चाहता हूं लेकिन 10 सबसे हाल ही में। मैं इसे एक कमांड में कैसे कर सकता हूं?
जवाबों:
एक पोर्टेबल और विश्वसनीय समाधान के लिए, यह प्रयास करें:
ls -1tr | head -n -10 | xargs -d '\n' rm -f --
tail -n -10अन्य उत्तर में से एक में वाक्य रचना (यानी, मेरी RHEL5 सिस्टम पर नहीं) हर जगह काम प्रतीत होता है नहीं।
और कमांड लाइन का उपयोग करके $()या उसके जोखिम को चलाता है``rm
xargsइन दोनों समस्याओं को हल करता है क्योंकि यह स्वचालित रूप से यह पता लगा -d '\n'लेगा कि यह वर्ण सीमा के भीतर कितने आर्गन से गुजर सकती है, और इसके साथ ही यह इनपुट की सीमा रेखा पर विभाजित हो जाएगी। तकनीकी रूप से यह अभी भी उन में एक नई रेखा के साथ फ़ाइल नाम के लिए समस्याएँ पैदा कर सकता है, लेकिन यह रिक्त स्थान के साथ फ़ाइलनाम की तुलना में बहुत कम आम है, और newlines के चारों ओर एकमात्र तरीका बहुत अधिक जटिल होगा, शायद कम से कम awk को शामिल करना, यदि नहीं perl।
यदि आपके पास xargs (पुराना AIX सिस्टम नहीं है, तो शायद) आप इसे लूप बना सकते हैं:
ls -1tr | head -n -10 | while IFS= read -r f; do
rm -f "$f"
done
यह थोड़ा धीमा होगा क्योंकि यह rmप्रत्येक फ़ाइल के लिए एक अलग स्पॉन बनाता है , लेकिन फिर भी ऊपर 1 और 2 कैविएट से बच जाएगा (लेकिन अभी भी फ़ाइल नामों में नई सुर्खियों से ग्रस्त है)।
head(1)मैन पेज से:-n, --lines=[-]K print the first K lines instead of the first 10; with the leading '-', print all but the last K lines of each file
headऔर xargsत्रुटियां दें। सही विकल्प हैं head -n 10और xargs rm -f। पूरी कमान हैls -1tr ./ | head -n 10 | xargs rm -rf
ls -1tr"L" अक्षर नहीं है।
वह कोड जिसे आप अपनी स्क्रिप्ट में शामिल करना चाहते हैं, वह है
rm -f $(ls -1t /path/to/your/logs/ | tail -n +11)
-1(संख्यात्मक एक) विकल्प प्रिंट एक पंक्ति पर प्रत्येक फ़ाइल, यह सुरक्षित है। जब कुछ भी नहीं लौटाता है तो गैर-मौजूद फ़ाइलों को अनदेखा -fकरने का विकल्प rmबताता है ls।
/path/to/your/logsहै कि आप सही राह में आने के लिए ही बने हैं। बग को खोजने के लिए भागों ls -t /path/...और ls -t /path/... | tail -n +11अकेले निष्पादित करें और जांचें कि क्या परिणाम सही है।
+संख्या से पहले मन । यह tailअंतिम n तत्वों को प्रिंट नहीं करता है, लेकिन सभी तत्व n'th से शुरू होते हैं। मैंने फिर से जाँच की और कमांड को निश्चित रूप से सभी परिस्थितियों में 10 सबसे हाल की फाइलों से पुराने तत्वों को हटाना चाहिए।
ls, एक फ़ाइल नाम प्रिंट करता है, न कि कोई रास्ता ताकि आपकी rm -fवर्तमान निर्देशिका में फ़ाइलों को हटाने का प्रयास किया जाए
जाहिर तौर पर पार्सिंग lsबुराई है ।
यदि प्रत्येक फ़ाइल प्रतिदिन बनाई जाती है और आप पिछले 10 दिनों के भीतर बनाई गई फ़ाइलों को रखना चाहते हैं, तो आप कर सकते हैं:
find /path/to/files -mtime 10 -delete
या यदि प्रत्येक फ़ाइल मनमाने ढंग से बनाई गई है:
find /path/to/files -maxdepth 1 -type f -printf '%Ts\t%P\n' | sort -n | head -n -10 | cut -f 2- | xargs rm -rf
-mtime 10 -deleteकेवल 10 दिन पहले संशोधित फ़ाइलों को हटाता है। पुरानी फाइलें हटाई नहीं जाएंगी। -mtime +11 -deleteपिछले 10 दिनों की लॉग फ़ाइलों को छोड़ कर 11 या अधिक दिनों में संशोधित की गई फ़ाइलों को हटा देगा।
%pइसके बजाय के उपयोग की %Pजरूरत है printfताकि फाइलों को पूरा रास्ता मिल सके। अन्यथा rm -rfकाम नहीं करता है।
मैंने इसहाक के दृष्टिकोण को थोड़ा संशोधित किया ।
यह अब एक वांछित पथ के साथ काम करता है:
ls -d -1tr /path/to/folder/* | head -n -10 | xargs -d '\n' rm -f
से यहाँ :
#! /bin/sh
# keepnewest
#
# Simple directory trimming tool to handle housekeeping
# Scans a directory and deletes all but the N newest files
#
# Usage: cleanup <dir> <number of files to keep>
#
# v 1.0 Piers Goodhew 1/mar/2007. No rights retained.
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 <dir> <number of files to keep>"
exit 1
fi
cd $1
files_in_dir=`ls | wc -l`
files_to_delete=`expr $files_in_dir - $2`
if [ $files_to_delete -gt 0 ]; then
ls -t | tail -n $files_to_delete | xargs rm
if [ $? -ne 0 ]; then
echo "An error ocurred deleting the files"
exit 1
else
echo "$files_to_delete file(s) deleted."
fi
else
echo "nothing to delete!"
fi
बैश में आप कोशिश कर सकते हैं:
ls -1t | (i=0; while read f; do
if [ $i -lt 10 ]; then
((i++))
continue
else
rm -f "$f"
fi
done)
यह 10 नवीनतम als बाकी को हटा देता है। logrotate बेहतर हो सकता है, मैं केवल गलत शेल संबंधित उत्तरों को सही करना चाहता हूं।
सुनिश्चित नहीं है कि यह किसी को भी मदद करेगा, लेकिन विंची पात्रों के साथ संभावित मुद्दों से बचने के लिए मैं सिर्फ lsसॉर्ट करने के लिए उपयोग करता हूं , लेकिन फिर inodeडिलीट के लिए फाइलों का उपयोग करता हूं ।
वर्तमान निर्देशिका के लिए, यह संशोधन के समय के आधार पर सबसे हाल की 10 फाइलें रखता है।
ls -1tri | awk '{print $1}' | head -n -10 | xargs -n1 -t -Iinode find . -inum inode -exec rm -i {} \;
मुझे व्यस्त बॉक्स (राउटर) के लिए एक सुरुचिपूर्ण समाधान की आवश्यकता थी, सभी xargs या सरणी समाधान मेरे लिए बेकार थे - ऐसा कोई भी कमांड उपलब्ध नहीं है। खोज और माइम उचित उत्तर नहीं है क्योंकि हम 10 वस्तुओं के बारे में बात कर रहे हैं और जरूरी नहीं कि 10 दिन हों। एस्पो का जवाब सबसे छोटा और सबसे साफ और सबसे अधिक संभावना वाला था।
रिक्त स्थान के साथ त्रुटि और जब कोई फ़ाइल नहीं हटाई जानी है, तो दोनों को बस मानक तरीके से हल किया गया है:
rm "$(ls -td *.tar | awk 'NR>7')" 2>&-
थोड़ा और अधिक शैक्षिक संस्करण: हम यह सब कर सकते हैं यदि हम अलग-अलग awk का उपयोग करते हैं। आम तौर पर, मैं इस पद्धति का उपयोग awk से sh तक (वापसी) चर को पास करने के लिए करता हूं। जैसा कि हम हर समय पढ़ते हैं जो नहीं किया जा सकता है, मैं अलग होने की भीख माँगता हूँ: यहाँ विधि है।
फ़ाइल नाम में रिक्त स्थान के बारे में कोई समस्या नहीं के साथ .tar फ़ाइलों के लिए उदाहरण। परीक्षण करने के लिए, "आरएमएस" को "एलएस" से बदलें।
eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')
स्पष्टीकरण:
ls -td *.tarसभी .tar फ़ाइलों को समय के अनुसार क्रमबद्ध करता है। वर्तमान फ़ोल्डर में सभी फ़ाइलों पर लागू करने के लिए, "d * .tar" भाग को हटा दें
awk 'NR>7... पहले 7 लाइनों को छोड़ देता है
print "rm \"" $0 "\"" एक लाइन का निर्माण करता है: rm "फ़ाइल का नाम"
eval इसे निष्पादित करता है
चूंकि हम उपयोग कर रहे हैं rm, इसलिए मैं उपरोक्त कमांड का उपयोग स्क्रिप्ट में नहीं करूंगा! समझदार उपयोग है:
(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))
ls -tआदेश का उपयोग करने के मामले में इस तरह के मूर्खतापूर्ण उदाहरणों पर कोई नुकसान नहीं होगा: touch 'foo " bar'और touch 'hello * world'। ऐसा नहीं है कि हम कभी वास्तविक जीवन में ऐसे नामों के साथ फाइल बनाते हैं!
पक्षीय लेख। अगर हम इस तरह से एक चर को पास करना चाहते हैं, तो हम बस प्रिंट को संशोधित करेंगे:
print "VarName="$1
VarNameके मान को चर सेट करने के लिए $1। एक बार में कई चर बनाए जा सकते हैं। यह VarNameएक सामान्य श वेरिएबल बन जाता है और सामान्य रूप से बाद में स्क्रिप्ट या शेल में उपयोग किया जा सकता है। इसलिए, awk के साथ वैरिएबल बनाने और उन्हें शेल में वापस देने के लिए:
eval $(ls -td *.tar | awk 'NR>7 { print "VarName="$1 }'); echo "$VarName"
इसहाक फ्रीमैन प्रतिक्रिया के आधार पर, लेकिन किसी भी निर्देशिका पर काम करना:
ls -1tr $PATH_TO_DELETE/* | head -n -10 | xargs -d '\n' rm -f --
आप उपसर्ग भी सेट कर सकते हैं, जैसे $PATH_TO_DELETE/testFi*
अगर आप निरपेक्ष फ़ाइल नामों *को PATH lsवसीयत के बाद उपयोग करते हैं , तो कम से कम "मेरे" बैश में :)