सबसे पुरानी फाइलों को हटा दें


9

मैं निर्देशिका से पुरानी फ़ाइलों को हटाने और केवल 3 नई फ़ाइलों को छोड़ने का प्रयास कर रहा हूं।

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

सशर्त बयान में कुछ गलत है।

जवाबों:


9

यदि आप फ़ाइलों पर लूप करना चाहते हैं, तो कभी भी उपयोग न करेंls *। tl; dr ऐसी बहुत सी स्थितियाँ हैं जहाँ आप गलत फ़ाइल या सभी फ़ाइलों को हटाना समाप्त कर देंगे।

उस ने कहा, दुर्भाग्य से यह बैश में सही करने के लिए एक मुश्किल काम है। वहाँ कम से ऊपर एक काम कर जवाब एक डुप्लिकेट सवाल मेरे यहां तक कि पुरानेfind_date_sorted जो आप छोटे संशोधनों के साथ उपयोग कर सकते हैं:

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

* कोई अपराध नहीं - मैं भी lsपहले इस्तेमाल किया । लेकिन यह वास्तव में सुरक्षित नहीं है।

संपादित करें: इकाई परीक्षणों के साथ नयाfind_date_sorted


मैं दूसरे भाग के बारे में ls पार्स नहीं कर रहा हूं। इसके अलावा स्क्रिप्ट साफ है, लेकिन मुझे लगता है कि यह एक लाइनर में किया जा सकता है, मुझे जांचने दो ...
rahmu

ठीक है, आप हमेशा एक-लाइनर में बैश कोड को कॉम्पैक्ट कर सकते हैं, लेकिन मुद्दा यह है कि क्या यह पठनीय होगा :)
l0b0

2
अगर मैं निर्दयता से @ पीटर.ओ से एक विचार चोरी कर सकता हूं, तो ((++counter>3))अपने परीक्षण के रूप में प्रयास करें। यह अच्छी तरह से रसीला है। ऑनलाइनर के रूप में: यदि संक्षिप्तता एक फ़ंक्शन में कोड को लपेटने की चिंता है, तो इसके बारे में चिंता न करें।
सोरपीगल

@ सोरीपगल नीट शॉर्टकट
l0b0

5

सभी को हटाने के लिए, लेकिन एक zsh ग्लोब का उपयोग करके 3 सबसे नई फाइलें, आप Om(कैपिटल ओ) का उपयोग करके फाइलों को सबसे पुरानी से लेकर नई तक छांट सकते हैं और अपनी पसंद की फाइलों को हथियाने के लिए एक सबस्क्रिप्ट कर सकते हैं।

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

अन्य उदाहरण:

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])

5

अब तक सबसे आसान तरीका है zsh और इसके ग्लोब क्वालीफायर का उपयोग करना : Omकम उम्र (जैसे सबसे पुराना) [1,3]को छाँटना और केवल पहले तीन मैचों को बरकरार रखना।

rm ./*(Om[1,3])

यह भी देखें कि मैं अधिक उदाहरणों के लिए zsh में ग्लोब कैसे फ़िल्टर कर सकता हूं

और l0b0 की सलाह पर ध्यान दें : यदि आपके पास फ़ाइल नाम हैं जिनमें शेल विशेष वर्ण हैं तो आपका कोड बुरी तरह से टूट जाएगा।


Woa ट्रेन पकड़ना, क्या यह वास्तव में 1 लाइन में पूर्ण समाधान है?
मेटागुरु

2
@Ryan यह आपके लिए zsh है।
गिल्स एसओ- बुराई को रोकना

1

निर्देशिका में नवीनतम फ़ाइल प्राप्त करने के लिए आप निम्न फ़ंक्शन का उपयोग कर सकते हैं:

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

प्रत्येक पुनरावृत्ति के बाद सबसे नई फ़ाइल को एक्सेल करके फाइलों का एक अलग सेट दें।

युक्ति: यदि आप "$ {फ़ाइलें [@]}" नामक एक सरणी में फ़ाइलों का प्रारंभिक सेट रखते हैं, तो मिली नई फ़ाइल के सूचकांक और unset 'files[index]'अगले पुनरावृत्ति से पहले सहेजें ।

उपयोग: newest_in [set of files/directories]

नमूना उत्पादन:

[rany$] newest_in ./*
foo.txt
[rany$]

-1

सबसे पहले, -Rविकल्प पुनरावृत्ति के लिए है, जो कि शायद आप क्या चाहते हैं - जो सभी उपनिर्देशिकाओं में भी खोज करेगा। दूसरा, <ऑपरेटर (जब पुनर्निर्देशन के रूप में नहीं देखा जा रहा है) स्ट्रिंग तुलना के लिए है। आप शायद चाहते हैं -lt। प्रयत्न:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

लेकिन मैं यहां खोजने का उपयोग करूंगा:

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]

यदि फ़ाइल के एक या अधिक नामों में '$ \ n' है तो दोनों विफल हो जाएंगे।
रानी अलबेग वेन

-1

मुझे पता है कि यह पाप करना पाप है ls, लेकिन इस बारे में क्या:

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

5 खाली फ़ाइलों के साथ एक त्वरित परीक्षण:

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5

यह एक दो कारणों से विफल हो जाएगा - पार्सिंग lsआउटपुट और उपयोग करना findऔर xargsएक साथ गलत तरीके से। यदि आप संयोजन करते हैं findऔर xargsमैं आपको finds -print0और तदनुसार xargss -Oविकल्पों का उपयोग करने की सलाह देता हूं । विषय के बारे में अधिक जानकारी के लिए खोज का उपयोग करने के बारे में पढ़ें । आप यह भी देख सकते हैं कि क्यों पार्सिंग एलएस बहुत खराब है।
रानी एल्बेग वेन

-2

यह एक-लाइनर यह सब मुझे लगता है:

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"

एलएस अंतःक्रियात्मक रूप से फ़ाइल जानकारी को देखने के लिए एक उपकरण है। इसका आउटपुट मनुष्यों के लिए स्वरूपित है और स्क्रिप्ट में कीड़े पैदा करेगा। इसके बजाय ग्लब्स का उपयोग करें या खोजें। इसे क्यों समझें: mywiki.wooledge.org/ParsingLs
Rani Albeg Wein

-2

यहाँ एक समाधान है:

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)

1
@bakbak ls इंटरएक्टिव रूप से फ़ाइल जानकारी देखने का एक उपकरण है। इसका आउटपुट मनुष्यों के लिए स्वरूपित है और स्क्रिप्ट में कीड़े पैदा करेगा। समझने के लिए यहां देखें । आपके उत्तर के बारे में विशेष रूप से बोलना - यह एक टूट जाएगा यदि एक या एक से अधिक फ़ाइलों में $ '\ n' वर्ण होता है। इसके अलावा, कमांड सब्स्टीट्यूशन (यानी $ (...) में दोहरे उद्धरणों का अभाव है जो एक और महत्वपूर्ण विषय लाता है - वर्ड स्प्लिटिंग !
रानी अलबेग वेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.