मैं लिनक्स में सभी 10 नई फाइलें कैसे हटाऊं?


49

मैं एक निर्देशिका को लॉग करने योग्य फ़ाइलों से भरा रखने की कोशिश कर रहा हूं। रात भर, मैं सभी को हटाना चाहता हूं लेकिन 10 सबसे हाल ही में। मैं इसे एक कमांड में कैसे कर सकता हूं?




@michael मेरा एक डुप्लिकेट कैसे हो सकता है, अगर मेरी चर्चा पहले बनाई गई थी?
dev4life

@ovaherenow "तुम्हारा"? मैं आपका नाम किसी भी प्रश्न पर नहीं देखता हूं, इसलिए मुझे यकीन नहीं है कि आपका क्या मतलब है। मेरी टिप्पणी यह ​​भी नहीं बताती है कि दूसरे की कौन सी नकल है। लेकिन इससे कोई फर्क नहीं पड़ता - यह सिर्फ एक टिप्पणी है, एक लिंक के साथ। इसे या तो प्रश्न या दोनों प्रश्नों में जोड़ा जा सकता है। यह किसी और पर निर्भर है - एक व्यवस्थापक - एक डुप्लिकेट के रूप में एक या दूसरे को चिह्नित करने के लिए। किसी भी नापाक मंसूबे का इरादा नहीं था और न ही किसी को माना जाना चाहिए। कौन सा सवाल पहले से ज्यादा महत्वपूर्ण था, कौन सा सवाल सबसे अच्छा जवाब है - फिर से, लिंक इस चर्चा की सुविधा देता है, यह जवाब निर्धारित नहीं करता है।
माइकल

@ चमेली वाह। यह वास्तव में अजीब है। यह धागा मेरे द्वारा खोला गया था लेकिन यह स्पष्ट रूप से मेरा उपयोगकर्ता नाम नहीं है। लेकिन मुझे इस धागे के बारे में सूचित किया जा रहा है।
dev4life

जवाबों:


58

एक पोर्टेबल और विश्वसनीय समाधान के लिए, यह प्रयास करें:

ls -1tr | head -n -10 | xargs -d '\n' rm -f --

tail -n -10अन्य उत्तर में से एक में वाक्य रचना (यानी, मेरी RHEL5 सिस्टम पर नहीं) हर जगह काम प्रतीत होता है नहीं।

और कमांड लाइन का उपयोग करके $()या उसके जोखिम को चलाता है``rm

  1. व्हॉट्सएप और
  2. अधिकतम कमांडलाइन वर्ण सीमा से अधिक है।

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
आइजैक फ्रीमैन

सोलारिस 10 पर headऔर xargsत्रुटियां दें। सही विकल्प हैं head -n 10और xargs rm -f। पूरी कमान हैls -1tr ./ | head -n 10 | xargs rm -rf
दिमित्रीसांडोव

1
नोट ls -1tr"L" अक्षर नहीं है।
shonky linux यूजर

1
यह भी ध्यान दिया जाना चाहिए कि एक्स्ट्रीम फिल्म्स में नए समाचार दुर्लभ लेकिन मान्य पात्र हैं। इसका मतलब यह है कि अगर आपके पास "उस", और "उस \ nthing" फाइलें हैं, यदि यह स्क्रिप्ट "उस \ n" से टकराती है, तो यह "उस" को हटा देगा, जब वह "चीज" को हटा नहीं सकता, तो त्रुटि "that \ nthing" (इच्छित लक्ष्य) अप्रभावित।
सिंथेट

1
@IsaacFreeman मैंने अपनी बुरी सलाह, चीयर्स को हटा दिया है।
वॉल्फ

20

वह कोड जिसे आप अपनी स्क्रिप्ट में शामिल करना चाहते हैं, वह है

 rm -f $(ls -1t /path/to/your/logs/ | tail -n +11)

-1(संख्यात्मक एक) विकल्प प्रिंट एक पंक्ति पर प्रत्येक फ़ाइल, यह सुरक्षित है। जब कुछ भी नहीं लौटाता है तो गैर-मौजूद फ़ाइलों को अनदेखा -fकरने का विकल्प rmबताता है ls


मूल पोस्टर, यहाँ। मैंने इस कमांड की कोशिश की, लेकिन यह काम नहीं करता - मुझे "rm: मिसिंग ऑपरेंड" की त्रुटि मिलती है
user75814

2
क्या आपने सही रास्ते का इस्तेमाल किया? जाहिर /path/to/your/logsहै कि आप सही राह में आने के लिए ही बने हैं। बग को खोजने के लिए भागों ls -t /path/...और ls -t /path/... | tail -n +11अकेले निष्पादित करें और जांचें कि क्या परिणाम सही है।
डैनियल बॉहेर

1
@HaLLaging मुझे पूरा यकीन है कि आपको कुछ गड़बड़ लगी। +संख्या से पहले मन । यह tailअंतिम n तत्वों को प्रिंट नहीं करता है, लेकिन सभी तत्व n'th से शुरू होते हैं। मैंने फिर से जाँच की और कमांड को निश्चित रूप से सभी परिस्थितियों में 10 सबसे हाल की फाइलों से पुराने तत्वों को हटाना चाहिए।
डैनियल बॉमर

@halo वास्तव में, क्षमा करें।
हौके लैगिंग

2
मुझे लगता है कि आपका जवाब बहुत खतरनाक है ls, एक फ़ाइल नाम प्रिंट करता है, न कि कोई रास्ता ताकि आपकी rm -fवर्तमान निर्देशिका में फ़ाइलों को हटाने का प्रयास किया जाए
Jürgen Steinblock

14

जाहिर तौर पर पार्सिंग 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

5
-mtime 10 -deleteकेवल 10 दिन पहले संशोधित फ़ाइलों को हटाता है। पुरानी फाइलें हटाई नहीं जाएंगी। -mtime +11 -deleteपिछले 10 दिनों की लॉग फ़ाइलों को छोड़ कर 11 या अधिक दिनों में संशोधित की गई फ़ाइलों को हटा देगा।
मार्कस

1
मुझे लगता है कि %pइसके बजाय के उपयोग की %Pजरूरत है printfताकि फाइलों को पूरा रास्ता मिल सके। अन्यथा rm -rfकाम नहीं करता है।
जलोपाबा

9

लॉगरोट जैसा उपकरण आपके लिए ऐसा करता है। यह लॉग प्रबंधन को बहुत आसान बनाता है। आप अतिरिक्त शुगर रूटीन शुच भी शामिल कर सकते हैं, जैसे कि हेलो सुगरस्टेड।



1

से यहाँ :

#! /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

1
यह उत्तर प्रदान करने के लिए धन्यवाद। इस तरह कोड प्रदान करना सहायक होता है, यह कुछ अतिरिक्त जानकारी प्रदान करने में भी मदद करता है कि इसका उपयोग कैसे किया जा सकता है या कोड क्या करता है। आप अपनी पोस्ट में भविष्य में सुधार करने के लिए संपादन बटन का उपयोग कर सकते हैं ।
nhinkle

1

बैश में आप कोशिश कर सकते हैं:

ls -1t | (i=0; while read f; do
  if [ $i -lt 10 ]; then
    ((i++))
    continue
  else
    rm -f "$f"
  fi
done)

यह 10 नवीनतम als बाकी को हटा देता है। logrotate बेहतर हो सकता है, मैं केवल गलत शेल संबंधित उत्तरों को सही करना चाहता हूं।


1

सुनिश्चित नहीं है कि यह किसी को भी मदद करेगा, लेकिन विंची पात्रों के साथ संभावित मुद्दों से बचने के लिए मैं सिर्फ lsसॉर्ट करने के लिए उपयोग करता हूं , लेकिन फिर inodeडिलीट के लिए फाइलों का उपयोग करता हूं ।

वर्तमान निर्देशिका के लिए, यह संशोधन के समय के आधार पर सबसे हाल की 10 फाइलें रखता है।

ls -1tri | awk '{print $1}' | head -n -10 | xargs -n1 -t -Iinode find . -inum inode -exec rm -i {} \;


0

मुझे व्यस्त बॉक्स (राउटर) के लिए एक सुरुचिपूर्ण समाधान की आवश्यकता थी, सभी 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"

0

मैं सहमत हूँ कि पार्सिंग ls बुराई है!

सुनिश्चित करें कि /srv/backupsमार्ग में केवल अंतिम 5 फाइलें रखी गई हैं ।

find /srv/backups -maxdepth 1 -type f -printf '%Ts\t%P\n' \
    | sort -rn \
    | tail -n +6 \
    | cut -f2- \
    | xargs -r r

0

इसहाक फ्रीमैन प्रतिक्रिया के आधार पर, लेकिन किसी भी निर्देशिका पर काम करना:

ls -1tr $PATH_TO_DELETE/* | head -n -10 | xargs -d '\n' rm -f --

आप उपसर्ग भी सेट कर सकते हैं, जैसे $PATH_TO_DELETE/testFi*

अगर आप निरपेक्ष फ़ाइल नामों *को PATH lsवसीयत के बाद उपयोग करते हैं , तो कम से कम "मेरे" बैश में :)

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