ব্যাশের মধ্যে অতি সাম্প্রতিক এক্স ফাইলগুলি বাদ দিয়ে সমস্ত মুছুন


157

ডিরেক্টরি থেকে সর্বাধিক এক্স ফাইলগুলি মুছে ফেলার জন্য একটি কমান্ড চালানোর জন্য বাশ সহ সুন্দর মানসম্পন্ন ইউনিক্স পরিবেশে কি কোনও সহজ উপায় আছে?

কিছুটা কংক্রিটের উদাহরণ দেওয়ার জন্য, কল্পনা করুন যে কিছু ক্রোন জব একটি ফাইল লিখুন (বলুন, একটি লগ ফাইল বা একটি টার-এড আপ ব্যাকআপ) প্রতি ঘন্টা একটি ডিরেক্টরিতে। আমি আরও একটি ক্রোন জব চালানোর একটি উপায় চাই যা 5 টির চেয়ে কম না হওয়া পর্যন্ত ডিরেক্টরিটি সর্বাধিক প্রাচীন ফাইলগুলি সরিয়ে ফেলবে।

এবং কেবল পরিষ্কার করার জন্য, কেবলমাত্র একটি ফাইল উপস্থিত রয়েছে, এটি কখনই মুছে ফেলা উচিত নয়।

উত্তর:


117

বিদ্যমান উত্তরগুলির সাথে সমস্যাগুলি:

  • এম্বেড করা স্পেস বা নতুনলাইন সহ ফাইলের নামগুলি হ্যান্ডেল করতে অক্ষমতা।
    • সমাধানগুলির ক্ষেত্রে যা rmসরাসরি অযোগ্য কমান্ড প্রতিস্থাপনের জন্য আহ্বান করে ( rm `...`), অযৌক্তিক গ্লোব্বিংয়ের আরও একটি ঝুঁকি রয়েছে।
  • ফাইল এবং ডিরেক্টরিগুলির মধ্যে পার্থক্য করতে অক্ষমতা (উদাহরণস্বরূপ, যদি ডিরেক্টরিগুলি 5 সম্প্রতি সংশোধিত ফাইল সিস্টেম আইটেমগুলির মধ্যে হয়ে থাকে, আপনি কার্যকরভাবে 5 টিরও কম ফাইল ধরে রাখতে পারবেন, এবং rmডিরেক্টরিতে প্রয়োগ করা ব্যর্থ হবে)।

Wnoise এর উত্তর এই সমস্যাগুলিকে সম্বোধন করে, তবে সমাধানটি GNU- স্পেসিফিক (এবং বেশ জটিল)।

এখানে একটি বাস্তববাদী, পসিএক্স-সম্মতিযুক্ত সমাধান যা কেবলমাত্র একটি ক্যাভিয়েট সহ আসে : এটি এম্বেড করা নতুন লাইনের সাথে ফাইলের নামগুলি পরিচালনা করতে পারে না - তবে আমি বেশিরভাগ মানুষের কাছে এটি বাস্তব-বিশ্বের উদ্বেগ বিবেচনা করি না।

রেকর্ডের জন্য, কেন lsআউটপুট পার্স করা ভাল ধারণা না কেন তার ব্যাখ্যা এখানে রয়েছে : http://mywiki.wooledge.org/ পার্সিংএল

ls -tp | grep -v '/$' | tail -n +6 | xargs -I {} rm -- {}

উপরে অদক্ষ , কারণ xargsডাকা হয়েছে rmএকবার প্রতিটি ফাইলের নাম।
আপনার প্ল্যাটফর্মগুলি xargsআপনাকে এই সমস্যাটি সমাধান করার অনুমতি দিতে পারে:

আপনার যদি জিএনইউ থাকে তবে xargs ব্যবহার করুন -d '\n', যা xargsপ্রতিটি ইনপুট লাইনটিকে পৃথক যুক্তি হিসাবে বিবেচনা করে, তবুও কমান্ড লাইনে একবারে যতটা যুক্তি তত যুক্তি পাস করে :

ls -tp | grep -v '/$' | tail -n +6 | xargs -d '\n' -r rm --

-r( --no-run-if-empty) নিশ্চিত করে যে rmকোনও ইনপুট না থাকলে অনুরোধ করা হয়নি।

আপনার যদি BSD xargs ( ম্যাকোস সহ ) রয়েছে, আপনি প্রথমে ( ) চরগুলিতে নতুন লাইনগুলি অনুবাদ করার পরে, সজ্জিত ইনপুট -0হ্যান্ডেল করতে ব্যবহার করতে পারেন , যা সমস্ত ফাইলের নাম একবারে পাস করে ( NULজিএনইউতেও কাজ করবে ):NUL0x0xargs

ls -tp | grep -v '/$' | tail -n +6 | tr '\n' '\0' | xargs -0 rm --

ব্যাখ্যা:

  • ls -tpক্রমবর্ধমান ক্রমে (সম্প্রতি সম্প্রতি পরিবর্তিত আইটেমগুলি প্রথমে) ( -t) এর আকার অনুসারে ফাইল সিস্টেম আইটেমগুলির নাম অনুসারে বাছাই করা হয়েছে , ডিরেক্টরিগুলি /( -p) হিসাবে চিহ্নিত করার জন্য এটি মুদ্রণ করা হয় ।
  • grep -v '/$'তারপর তালিকা, বাদ দ্বারা ফলে (থেকে ডিরেক্টরি আউট যেটি -v) লাইন একটি trailing আছে /( /$)।
    • ক্যাভেট : যেহেতু একটি ডিরেক্টরিকে নির্দেশ করে এমন একটি সিমলিংক প্রযুক্তিগতভাবে নিজেই ডিরেক্টরি নয়, সুতরাং এই জাতীয় চিহ্নগুলি বাদ দেওয়া হবে না
  • tail -n +6প্রথম অগ্রাহ্য 5 তালিকা এন্ট্রি, সব ফিরে কার্যকরী কিন্তু 5 সম্প্রতি পরিবর্তিত ফাইল, যদি থাকে।
    নোট করুন যে Nফাইলগুলি বাদ দেওয়ার জন্য N+1অবশ্যই পাস করতে হবে tail -n +
  • xargs -I {} rm -- {}(এবং এর বৈচিত্রগুলি) এরপরে rmএই সমস্ত ফাইলগুলিতে প্রার্থনা করে ; যদি কোনও মিল নেই তবে xargsকিছু করবেন না।
    • xargs -I {} rm -- {}স্থানধারককে সংজ্ঞায়িত করে {}যা প্রতিটি ইনপুট লাইনকে সামগ্রিকভাবে উপস্থাপন করে , তাই rmপ্রতিটি ইনপুট লাইনের জন্য একবার অনুরোধ করা হয় তবে এম্বেড থাকা ফাঁকা স্থানের ফাইলের নামগুলি সঠিকভাবে পরিচালনা করা হয়।
    • --সব ক্ষেত্রেই নিশ্চিত করে যে কোনও ফাইলের নাম যা শুরু হয় -সেগুলি বিকল্পগুলির জন্য ভুল না করে rm

মূল সমস্যার ক্ষেত্রে একটি প্রকরণ , যদি মিলের ফাইলগুলি পৃথকভাবে প্রক্রিয়া করা বা শেল অ্যারেতে সংগ্রহ করা প্রয়োজন :

# One by one, in a shell loop (POSIX-compliant):
ls -tp | grep -v '/$' | tail -n +6 | while IFS= read -r f; do echo "$f"; done

# One by one, but using a Bash process substitution (<(...), 
# so that the variables inside the `while` loop remain in scope:
while IFS= read -r f; do echo "$f"; done < <(ls -tp | grep -v '/$' | tail -n +6)

# Collecting the matches in a Bash *array*:
IFS=$'\n' read -d '' -ra files  < <(ls -tp | grep -v '/$' | tail -n +6)
printf '%s\n' "${files[@]}" # print array elements

2
অবশ্যই এখানে অন্যান্য উত্তরগুলির চেয়ে ভাল, তাই আমি আমার সমর্থন supportণ দিতে পেরে খুশি, এমনকি আমি যখনই নিউলাইন কেসকে এড়িয়ে চলা কেবল সতর্কতার সাথে করা জিনিস হিসাবে বিবেচনা করি।
চার্লস ডাফি

2
আপনি যদি lsবর্তমান ডিরেক্টরিটিতে না থাকেন তবে ফাইলের পথে '/' থাকবে, যার অর্থ grep -v '/'কোনও কিছুর সাথে মেলে না। আমি বিশ্বাস করি grep -v '/$'যা আপনি কেবল ডিরেক্টরিগুলি বাদ দিতে চান।
ওয়ালডল 1

1
@ ওয়ালডল 1: ধন্যবাদ; আমি আপনার পরামর্শ অন্তর্ভুক্ত করার জন্য উত্তর আপডেট করেছি, যা grepকমান্ডটি ধারণাগতভাবে আরও পরিষ্কার করে। দ্রষ্টব্য, তবে, আপনি যে সমস্যাটি বর্ণনা করেছেন তা কোনও একক ডিরেক্টরি পথের সাথে প্রকাশিত হয়নি ; উদাহরণস্বরূপ, ls -p /private/varএখনও কেবল নিছক ফাইলের নাম মুদ্রণ করতে হবে। আপনি যদি একাধিক ফাইল আর্গুমেন্ট (সাধারণত একটি গ্লোব মাধ্যমে) পাস করেন তবেই আপনি আউটপুটে আসল পাথ দেখতে পাবেন; যেমন, ls -p /private/var/*(এবং আপনার কাছে মিলে সাবডিরেক্টরি সামগ্রীগুলি দেখতে না যদি না আপনি এছাড়াও অন্তর্ভুক্ত -d)।
mklement0

108

ডিরেক্টরিতে সর্বাধিক সাম্প্রতিক ফাইলগুলির মধ্যে 5 (বা যাই হোক না কেন সংখ্যা) সমস্ত সরিয়ে ফেলুন।

rm `ls -t | awk 'NR>5'`

2
আমার আর্কাইভ ফাইলগুলি বিবেচনা করার জন্য আমার এটি প্রয়োজন। পরিবর্তন ls -tকরুনls -td *.bz2
জেমস টি স্নেল

3
আমি এটি ডিরেক্টরিতে rm -rf এ পরিবর্তন করে ব্যবহার করেছি ls -t | awk 'NR>1'(আমি কেবল সাম্প্রতিকতম চেয়েছিলাম)। ধন্যবাদ!
lohiaguitar91

11
ls -t | awk 'NR>5' | xargs rm -f আপনি যদি পাইপগুলিকে পছন্দ করেন এবং যদি মুছে ফেলার কিছু না থাকে তবে আপনার ত্রুটিটি দমন করতে হবে।
H2ONaCl

16
সংক্ষিপ্ত এবং পাঠযোগ্য, সম্ভবত, তবে ব্যবহার করা বিপজ্জনক; যদি এটি দিয়ে তৈরি একটি ফাইল মুছতে চেষ্টা করে touch 'hello * world', এটি বর্তমান ডিরেক্টরিতে একেবারে সবকিছু মুছে ফেলবে ।
চার্লস ডাফি

1
যদিও এর উত্তর দেওয়া হয়েছিল ২০০৮ সালে এটি একটি কবজির মতো কাজ করে এবং ঠিক একটি নির্দিষ্ট ডিরেক্টরি থেকে পুরানো ব্যাকআপগুলি মুছতে আমার যা প্রয়োজন ছিল তা ঠিক। অসাধারণ.
রেনস টিলম্যান

86
(ls -t|head -n 5;ls)|sort|uniq -u|xargs rm

এই সংস্করণটি স্পেস সহ নামগুলি সমর্থন করে:

(ls -t|head -n 5;ls)|sort|uniq -u|sed -e 's,.*,"&",g'|xargs rm

20
এই কমান্ডটি নামগুলির ফাঁক দিয়ে ফাইলগুলি সঠিকভাবে পরিচালনা করবে না।
টাইলার

5
(ls -t|head -n 5;ls)একটি কমান্ড গ্রুপ । এটি 5 টি সাম্প্রতিক ফাইলগুলি দুবার মুদ্রণ করে। sortঅভিন্ন লাইন একসাথে রাখে। uniq -uসদৃশগুলি সরিয়ে দেয়, যাতে 5 অতি সাম্প্রতিক ফাইলগুলি থেকে বাকি থাকে। তাদের প্রত্যেককে xargs rmকল rmকরে।
ফাবিয়েন

15
এটি আপনার সমস্ত ফাইল মুছবে যদি আপনার 5 বা তার চেয়ে কম থাকে! যোগ --no-run-if-emptyকরার জন্য xargsহিসেবে (ls -t|head -n 5;ls)|sort|uniq -u|xargs --no-run-if-empty rmদয়া করে উত্তর দিন আপডেট করুন।
গনফি ড্যান স্যাচাল

3
এমনকি "স্পেসের সাথে নামগুলিকে সমর্থন করে" এমন একটিটি বিপজ্জনক। এমন একটি নাম বিবেচনা করুন যাতে আক্ষরিক উক্তি রয়েছে: touch 'foo " bar'কমান্ডের পুরো অংশটি ফেলে দেবে।
চার্লস ডাফি

2
... xargs -d $'\n'আপনার সামগ্রীতে উদ্ধৃতি ইনজেক্ট করার চেয়ে এটি ব্যবহার করা আরও নিরাপদ , যদিও ইনপুট স্ট্রিমটি NU- সীমানা (যা সত্যিকারেরls জন্য সঠিকভাবে করা ছাড়া অন্য কিছু ব্যবহার করা প্রয়োজন ) আদর্শ বিকল্প।
চার্লস ডাফি

59

থেলসডজের উত্তরের সরল রূপ:

ls -tr | head -n -5 | xargs --no-run-if-empty rm 

ls -tr সমস্ত ফাইল প্রদর্শন করে, সবচেয়ে পুরনো প্রথম (-তিনিষ্ঠতম প্রথম, -র বিপরীত)।

হেড -n -5 5 টি সর্বশেষ লাইন (অর্থাৎ 5 টি নতুন ফাইল) ব্যতীত সমস্ত প্রদর্শন করে।

xargs আরএম প্রতিটি নির্বাচিত ফাইলের জন্য আরএম কল করে।


15
এক্সার্গসে --no-run-if-খালি যুক্ত করা দরকার যাতে 5 টিরও কম ফাইল থাকা অবস্থায় এটি ব্যর্থ হয়।
টম

ls -1tr | মাথা -n -5 | xargs rm <---------- আপনাকে ls তে একটি -1 যুক্ত করতে হবে বা সঠিকভাবে বিরুদ্ধে কাজ করার জন্য আপনি কোনও তালিকা আউটপুট পাবেন না
আল জোসলিন

3
-1পাইপলাইনে যখন আউটপুট আসে তখন আলজসলিন ডিফল্ট হয়, সুতরাং এটি এখানে বাধ্যতামূলক নয়। xargsস্পেস, কোট, এবং সি এর সাথে নামগুলি পার্স করার সময় এর ডিফল্ট আচরণ সম্পর্কিত অনেক বড় সমস্যা রয়েছে ।
চার্লস ডাফি

মনে হচ্ছে এটি --no-run-if-emptyআমার শেলের মধ্যে স্বীকৃত নয়। আমি উইন্ডোজে সিএমডার ব্যবহার করছি।
স্টিফুলিশ

-0যদি ফাইলের নামগুলিতে শ্বেত স্পেস থাকতে পারে তবে বিকল্পটি ব্যবহার করা দরকার । যদিও এটি এখনও পরীক্ষা করা হয়নি। উত্স
কিথ

18
find . -maxdepth 1 -type f -printf '%T@ %p\0' | sort -r -z -n | awk 'BEGIN { RS="\0"; ORS="\0"; FS="" } NR > 5 { sub("^[0-9]*(.[0-9]*)? ", ""); print }' | xargs -0 rm -f

জিএনইউ-প্রিন্টফের জন্য জিএনইউ অনুসন্ধান করতে হবে এবং -জেডের জন্য জিএনইউ বাছাই করতে হবে, এবং "\ 0" এর জন্য জিএনইউ অ্যাড্ক, এবং -0-এর জন্য জিএনইউ xargs রয়েছে, তবে এমবেডড নিউলাইনস বা স্পেস সহ ফাইলগুলি পরিচালনা করে।


2
আপনি যদি ডিরেক্টরিগুলি সরাতে চান তবে কেবল -f কে a-d তে পরিবর্তন করুন এবং আরএম-এ একটি -r যুক্ত করুন। অনুসন্ধান . -ম্যাক্সডেপথ 1-টাইপ ডি -প্রিন্টফ '% টি @% পি \ 0' | সাজানো -r -z -n | awk 'BEGIN {RS = "\ 0"; ওআিএস = "\ 0"; এফএস = ""} এনআর> 5 {উপ ("^ [0-9] * (। [[0-9] *)?", "")); মুদ্রণ} '| xargs -0 rm -rf
অ্যালেক্স

1
এক নজরে, আমি awkযুক্তিটির জটিলতা (বা, এই বিষয়টির জন্য, প্রয়োজন) দেখে অবাক হয়েছি । আমি কি ওপি-র প্রশ্নের অভ্যন্তরে এমন কিছু প্রয়োজনীয়তা অনুভব করছি যা এটি প্রয়োজনীয় করে?
চার্লস ডফি

@ চার্লস ডাফি: সাব () টাইমস্ট্যাম্পটি সরিয়ে দেয়, যা এটি সাজানো হয়। "% T @" দ্বারা উত্পাদিত টাইমস্ট্যাম্পে ভগ্নাংশের অংশ অন্তর্ভুক্ত থাকতে পারে। এফএস সহ স্পেসে বিভক্ত করা এম্বেড থাকা স্পেসগুলির সাথে পাথগুলি বিরতি দেয়। আমি মনে করি প্রথম স্থানের কাজগুলি সরিয়ে ফেলতে পারছি, তবে পড়া প্রায় কঠিন। আরএস এবং ওআরএস বিভাজকগুলি কমান্ড লাইনে সেট করা যায় না, কারণ এগুলি NULs।
জানুন

1
@ ননয়েস, আমার এ সম্পর্কে আমার স্বাভাবিক পদ্ধতির হ'ল শেল while read -r -d ' '; IFS= -r -d ''; do ...লুপে পাইপ দেওয়া - প্রথম পড়াটি স্পেসে শেষ হয়, যখন দ্বিতীয়টি NUL এ যায়।
চার্লস ডাফি

@ চারেলস ডাফি: আমি সবসময় কাঁচা শেলের উদ্রেক করি, সম্ভবত বাইজেন্টাইন উদ্বেগের কথা বলেছিলেন। আমি এখন sed -z -e 's/[^ ]* //; 1,5d'জিএনইউকে সবচেয়ে পরিষ্কার বলে মনে করি । (অথবা হয়ত sed -n -z -e 's/[^ ]* //; 6,$p'
wnoise

14

বর্তমান ডিরেক্টরিতে ডিরেক্টরি রয়েছে যখন এই সমস্ত উত্তর ব্যর্থ হয়। এখানে কাজ করে এমন কিছু:

find . -maxdepth 1 -type f | xargs -x ls -t | awk 'NR>5' | xargs -L1 rm

এই:

  1. বর্তমান ডিরেক্টরিতে ডিরেক্টরি রয়েছে যখন কাজ করে

  2. পূর্ববর্তী ফাইলটি সরানো না গেলেও প্রতিটি অনুমতি সরানোর চেষ্টা করে (অনুমতি ইত্যাদির কারণে)

  3. নিরাপদে ব্যর্থ হয় যখন বর্তমান ডিরেক্টরিতে ফাইলগুলির সংখ্যা অতিরিক্ত থাকে এবং xargsসাধারণত আপনাকে দাগিয়ে দেয় (দ্য -x)

  4. ফাইলের নামগুলিতে শূন্যস্থান পূরণ করে না (সম্ভবত আপনি ভুল ওএস ব্যবহার করছেন?)


5
যদি findএকক কমান্ড লাইনে আরও বেশি ফাইলের নাম প্রদান করা যায় তবে কী হবে ls -t? (ইঙ্গিত: আপনি একাধিক রান পান ls -t, যার প্রত্যেকটি কেবলমাত্র স্বতন্ত্রভাবে সঠিকভাবে সাজানো হয়, বিশ্বব্যাপী সঠিকভাবে সাজানোর ক্রম না করে; সুতরাং, যথেষ্ট পরিমাণ বড় ডিরেক্টরিতে চলাকালীন এই উত্তরটি খারাপভাবে ভেঙে যায়)।
চার্লস ডাফি

12
ls -tQ | tail -n+4 | xargs rm

প্রতিটি ফাইলের নাম উদ্ধৃত করে সংশোধন সময় দ্বারা ফাইলের নাম তালিকাভুক্ত করুন। প্রথম 3 বাদ দিন (3 অতি সাম্প্রতিক)। বাকিটি সরান।

Mklement0 (ধন্যবাদ!) থেকে সহায়ক মন্তব্যের পরে সম্পাদনা করুন: সংশোধন -n + 3 আর্গুমেন্ট, এবং নোট করুন যদি ফাইলের নামগুলিতে নতুন লাইন থাকে এবং / অথবা ডিরেক্টরিতে সাব-ডিরেক্টরি থাকে তবে এটি প্রত্যাশার মতো কাজ করবে না।


-Qবিকল্প আমার মেশিনে অস্তিত্ব মনে হচ্ছে না।
পিয়েরে-অ্যাড্রিয়েন

4
হুম, বিকল্পটি জিএনইউ কোর ব্যবহার করছে ~ 20 বছর ধরে, তবে বিএসডি ভেরিয়েন্টগুলিতে উল্লেখ করা হয়নি। আপনি একটি ম্যাক হয়?
চিহ্নিত করুন

আমি যথার্থই. আপ-টু-ডেট সিস্টেমগুলির মধ্যে এই ধরণের সত্যিকারের বুনিয়াদি কমান্ডগুলির মধ্যে পার্থক্য রয়েছে বলে ভাবেননি। আপনার উত্তরের জন্য ধন্যবাদ !
পিয়েরে-অ্যাড্রিয়েন

3
@ মার্ক: ++ এর জন্য -Q। হ্যাঁ, -Qএকটি জিএনইউ এক্সটেনশন (এখানে পসিক্স lsস্পেকটি রয়েছে )। একটি ছোট ক্যাভিয়েট (বাস্তবে খুব কমই সমস্যা): -Qফাইলনামগুলিকে আক্ষরিক হিসাবে এম্বেড করা নিউলাইনগুলি এনকোড দেয় \nযা rmস্বীকৃতি দেয় না। প্রথম 3 বাদ দিতে , xargsযুক্তিটি অবশ্যই আবশ্যক +4। অবশেষে, একটি সতর্কবাণী যা অন্যান্য অন্যান্য উত্তরের ক্ষেত্রেও প্রযোজ্য: আপনার কমান্ডটি কেবল তখনই উদ্দেশ্য হিসাবে কাজ করবে যদি বর্তমান দিরের কোনও উপ - ডিরেক্টরি নেই ।
mklement0

1
যখন অপসারণ করার মতো কিছুই নেই, আপনি --no-run-if-emptyবিকল্প সহ xargs কল করতে পারেন :ls -tQ | tail -n+4 | xargs --no-run-if-empty rm
অলিভিয়ার লেক্রিভাইন

8

নতুন লাইনগুলি উপেক্ষা করা সুরক্ষা এবং ভাল কোডিং উপেক্ষা করছে। Wnoise একমাত্র ভাল উত্তর ছিল। এখানে তার মধ্যে একটি প্রকরণ যা ফাইলের নামগুলিকে একটি অ্যারে $ x রাখে

while IFS= read -rd ''; do 
    x+=("${REPLY#* }"); 
done < <(find . -maxdepth 1 -printf '%T@ %p\0' | sort -r -z -n )

2
আমি সাফ করার পরামর্শ দিই IFS- অন্যথায় আপনি ফাইলের নাম থেকে শুকনো স্থান হারাতে ঝুঁকিপূর্ণ হবেন। পঠন কমান্ডের সুযোগটি while IFS= read -rd ''; do
চার্লস ডাফি

1
কেন "${REPLY#* }"?
msciwoj

4

যদি ফাইলের নামগুলির স্থান না থাকে তবে এটি কাজ করবে:

ls -C1 -t| awk 'NR>5'|xargs rm

যদি ফাইলনামগুলির স্পেস থাকে তবে এর মতো কিছু

ls -C1 -t | awk 'NR>5' | sed -e "s/^/rm '/" -e "s/$/'/" | sh

প্রাথমিক যুক্তি:

  • সময় অনুসারে ফাইলগুলির একটি তালিকা পান, একটি কলাম
  • প্রথম 5 ব্যতীত সমস্ত পান (এই উদাহরণের জন্য এন = 5)
  • প্রথম সংস্করণ: আরএম এ পাঠান
  • দ্বিতীয় সংস্করণ: একটি স্ক্রিপ্ট জেন করুন যা সেগুলি সঠিকভাবে সরিয়ে ফেলবে

while readস্থানগুলির সাথে কাজ করার কৌশলটি ভুলে যাবেন না : ls -C1 -t | awk 'NR>5' | while read d ; do rm -rvf "$d" ; done
পিনকেন

1
@ পিনকেন, সেখানে দেওয়া মত নিরাপদ নয়। while IFS= read -r dকিছুটা ভাল হতে পারে - -rব্যাকস্ল্যাশ লিটারালগুলি গ্রাস হওয়া থেকে বাধা দেয় readএবং IFS=হোয়াইটস্পেসের পিছনে স্বয়ংক্রিয়ভাবে ছাঁটাই প্রতিরোধ করে।
চার্লস ডাফি

4
বিটিডাব্লু, যদি কেউ প্রতিকূল ফাইল নামগুলি নিয়ে চিন্তিত হয় তবে এটি একটি অত্যন্ত বিপজ্জনক পদ্ধতি। দিয়ে তৈরি একটি ফাইল বিবেচনা করুন touch $'hello \'$(rm -rf ~)\' world'; ফাইলনামের অভ্যন্তরে আক্ষরিক উক্তিগুলি আপনি যে আক্ষরিক উক্তির সাথে যোগ করছেন তা প্রতিহত করবে sed, ফলস্বরূপ ফাইলের মধ্যে কোডটি কার্যকর করা হবে।
চার্লস ডাফি

1
(পরিষ্কার করার জন্য, উপরের "এই "টি সেই | shফর্মটির কথা উল্লেখ করছিল যা শেল ইঞ্জেকশন দুর্বলতার সাথে একটি)।
চার্লস ডাফি

2

Zsh সহ

ধরে নিচ্ছি যে আপনি বর্তমান ডিরেক্টরিগুলি সম্পর্কে চিন্তা করেন না এবং আপনার কাছে 999 টিরও বেশি ফাইল থাকবে না (আপনি চাইলে একটি বড় সংখ্যা চয়ন করুন বা কিছুক্ষণ লুপ তৈরি করুন)।

[ 6 -le `ls *(.)|wc -l` ] && rm *(.om[6,999])

ইন *(.om[6,999]), .মানে ফাইলগুলি, oমানে সাজানো অর্ডার আপ, mপরিবর্তনের তারিখ অনুসারে উপায় ( aঅ্যাক্সেসের সময় বা cইনোড পরিবর্তনের জন্য রাখা), অনেকগুলি [6,999]ফাইল চয়ন করে, তাই প্রথমে 5 টি আরএম করে না।


আকর্ষণীয়, তবে আমার জীবনের জন্য আমি বাছাই করা গ্লোব কোয়ালিফায়ারকে ( om) কাজ করতে পারিনি (আমি চেষ্টা করেছি যে কোনও ধরণের বাছাইয়ের কোনও প্রভাব নেই - OSX 10.11.2 এও নয় (zsh 5.0.8 এবং 5.1.1 দিয়ে চেষ্টা করেছি)) , না উবুন্টু 14.04 (zsh 5.0.2) - আমি কী অনুপস্থিত? হার্ড কোড করার কোন প্রয়োজন তা কেবল ব্যবহার করুন: পরিসর শেষবিন্দু হিসাবে -1এবং গত এন্ট্রি উল্লেখ করতে এইভাবে সব অবশিষ্ট ফাইল অন্তর্ভুক্ত: [6,-1]
mklement0

2

আমি বুঝতে পারি এটি একটি পুরানো থ্রেড, তবে সম্ভবত কেউ এ থেকে উপকৃত হবেন। এই কমান্ডটি বর্তমান ডিরেক্টরিতে ফাইলগুলি সন্ধান করবে:

for F in $(find . -maxdepth 1 -type f -name "*_srv_logs_*.tar.gz" -printf '%T@ %p\n' | sort -r -z -n | tail -n+5 | awk '{ print $2; }'); do rm $F; done

এটি পূর্ববর্তী উত্তরগুলির তুলনায় কিছুটা বেশি শক্তিশালী কারণ এটি আপনার অনুসন্ধান ডোমেনটিকে ফাইলের সাথে মিল রেখে সীমাবদ্ধ করতে দেয়। প্রথমে, আপনি যে কোনও শর্তে চান ফাইলের সন্ধান করুন। পাশের টাইমস্ট্যাম্পগুলি সহ সেই ফাইলগুলি মুদ্রণ করুন।

find . -maxdepth 1 -type f -name "*_srv_logs_*.tar.gz" -printf '%T@ %p\n'

এরপরে, তাদের টাইমস্ট্যাম্পগুলি অনুসারে বাছাই করুন:

sort -r -z -n

তারপরে, তালিকা থেকে 4 অতি সাম্প্রতিক ফাইলগুলি ছুঁড়ে ফেলুন:

tail -n+5

দ্বিতীয় কলামটি ধরুন (ফাইলের নাম, টাইমস্ট্যাম্প নয়):

awk '{ print $2; }'

এবং তারপরে সেই পুরো জিনিসটিকে একটি বিবৃতিতে জড়িয়ে দিন:

for F in $(); do rm $F; done

এটি আরও ভার্বোজ কমান্ড হতে পারে তবে শর্তসাপেক্ষে ফাইলগুলি লক্ষ্যবস্তু করতে এবং তাদের বিরুদ্ধে আরও জটিল কমান্ড কার্যকর করতে পেরে আমার ভাগ্য ভাল হয়েছিল।


1

সেড-অনলাইনারগুলিতে আকর্ষণীয় সেন্টিমিডে পাওয়া গেছে - শেষ 3 টি লাইন মুছুন - এটি বিড়ালের চামড়ার অন্য কোনও উপায়ে উপযুক্ত (ঠিক আছে না) তবে ধারণাটি:

 #!/bin/bash
 # sed cmd chng #2 to value file wish to retain

 cd /opt/depot 

 ls -1 MyMintFiles*.zip > BigList
 sed -n -e :a -e '1,2!{P;N;D;};N;ba' BigList > DeList

 for i in `cat DeList` 
 do 
 echo "Deleted $i" 
 rm -f $i  
 #echo "File(s) gonzo " 
 #read junk 
 done 
 exit 0

1

10 টি সর্বশেষ (সর্বাধিক রিসেন্ট) ফাইলগুলি বাদ দিয়ে সমস্ত সরিয়ে দেয়

ls -t1 | head -n $(echo $(ls -1 | wc -l) - 10 | bc) | xargs rm

10 টিরও কম ফাইল হলে কোনও ফাইল সরানো হয় না এবং আপনার কাছে রয়েছে: ত্রুটি শিরোনাম: অবৈধ লাইন গণনা - 0

বাশ দিয়ে ফাইল গণনা করা


1

আমার ব্যস্তবক্স (রাউটার) এর জন্য একটি মার্জিত সমাধান দরকার ছিল, সমস্ত xargs বা অ্যারের সমাধানগুলি আমার পক্ষে অকেজো - সেখানে এই জাতীয় কোনও আদেশ উপলব্ধ নেই available আমরা 10 টি আইটেমের কথা বলছি এবং অগত্যা 10 দিন নয়, কারণ অনুসন্ধান এবং এমটাইম সঠিক উত্তর নয়। এস্পোর উত্তরটি সবচেয়ে সংক্ষিপ্ত এবং পরিষ্কার এবং সম্ভবত সবচেয়ে বিপরীত ছিল।

স্পেসগুলির সাথে ত্রুটি এবং যখন কোনও ফাইল মুছতে হয় না তখন উভয়ই স্ট্যান্ডার্ড পদ্ধতিতে সমাধান করা হয়:

rm "$(ls -td *.tar | awk 'NR>7')" 2>&-

আরও শিক্ষামূলক সংস্করণে বিট করুন: আমরা যদি অন্যভাবে জঞ্জাল ব্যবহার করি তবে আমরা এটি সব করতে পারি। সাধারণত, আমি এই পদ্ধতিটি ব্যবহার করে ভেরিয়েবলগুলি sh থেকে sh এ ফিরে যেতে (রিটার্ন) করতে পারি। যেহেতু আমরা পুরোটা সময় পড়তে পারি না যা করতে পারি না, আমি আলাদা হতে অনুরোধ করি: এই পদ্ধতিটি এখানে।

ফাইলের নামের ফাঁকা স্থান নিয়ে কোনও সমস্যা না করে .tar ফাইলগুলির উদাহরণ। পরীক্ষা করতে, "আরএস" "ls" এর সাথে প্রতিস্থাপন করুন।

eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}')

ব্যাখ্যা:

ls -td *.tarসময় অনুসারে বাছাই করা সমস্ত .tar ফাইলগুলি তালিকাবদ্ধ করে। বর্তমান ফোল্ডারে থাকা সমস্ত ফাইলগুলিতে প্রয়োগ করতে, "ডি * .আর" অংশটি সরান

awk 'NR>7... প্রথম 7 লাইন এড়িয়ে যায়

print "rm \"" $0 "\"" একটি লাইন তৈরি করে: আরএম "ফাইলের নাম"

eval এটি কার্যকর করে

যেহেতু আমরা ব্যবহার করছি rm, আমি উপরের কমান্ডটি কোনও স্ক্রিপ্টে ব্যবহার করব না! উইজার ব্যবহারটি হ'ল:

(cd /FolderToDeleteWithin && eval $(ls -td *.tar | awk 'NR>7 { print "rm \"" $0 "\""}'))

ls -tকমান্ড ব্যবহারের ক্ষেত্রে যেমন নিরীহ উদাহরণগুলিতে কোনও ক্ষতি করে না: touch 'foo " bar'এবং touch 'hello * world'। বাস্তব জীবনে আমরা কখনও এই জাতীয় নাম দিয়ে ফাইল তৈরি করি না!

সাইড নোট. আমরা যদি এইভাবে sh এর কাছে একটি ভেরিয়েবল পাস করতে চাইতাম, তবে আমরা কেবল মুদ্রণটি পরিবর্তন করব (সাধারণ ফর্ম, কোনও ফাঁকা জায়গা সহ্য করা হয় না):

print "VarName="$1

পরিবর্তনশীল সেট করতে VarNameমূল্য $1। একযোগে একাধিক ভেরিয়েবল তৈরি করা যেতে পারে। এটি VarNameএকটি সাধারণ sh পরিবর্তনশীল হয়ে যায় এবং পরে কোনও স্ক্রিপ্ট বা শেল এ সাধারণত ব্যবহার করা যেতে পারে। সুতরাং, awk সহ ভেরিয়েবলগুলি তৈরি করতে এবং সেগুলি শেলের কাছে ফিরিয়ে দিতে:

eval $(ls -td *.tar | awk 'NR>7 { print "VarName=\""$1"\""  }'); echo "$VarName"

0
leaveCount=5
fileCount=$(ls -1 *.log | wc -l)
tailCount=$((fileCount - leaveCount))

# avoid negative tail argument
[[ $tailCount < 0 ]] && tailCount=0

ls -t *.log | tail -$tailCount | xargs rm -f

2
xargsছাড়া -0বা ন্যূনতমরূপে -d $'\n'অবিশ্বস্ত হয়; এটি খালি ফাঁকা বা এর নামে উদ্ধৃতি অক্ষর সহ একটি ফাইলের সাথে কী আচরণ করে তা পর্যবেক্ষণ করুন।
চার্লস ডাফি

0

আমি এটিকে ব্যাশ শেল স্ক্রিপ্টে তৈরি করেছি। ব্যবহার: keep NUM DIRযেখানে NUM ফাইল রাখার ফাইলের সংখ্যা এবং ডিআইআর হ'ল স্ক্র্যাব করার জন্য ডিরেক্টরি।

#!/bin/bash
# Keep last N files by date.
# Usage: keep NUMBER DIRECTORY
echo ""
if [ $# -lt 2 ]; then
    echo "Usage: $0 NUMFILES DIR"
    echo "Keep last N newest files."
    exit 1
fi
if [ ! -e $2 ]; then
    echo "ERROR: directory '$1' does not exist"
    exit 1
fi
if [ ! -d $2 ]; then
    echo "ERROR: '$1' is not a directory"
    exit 1
fi
pushd $2 > /dev/null
ls -tp | grep -v '/' | tail -n +"$1" | xargs -I {} rm -- {}
popd > /dev/null
echo "Done. Kept $1 most recent files in $2."
ls $2|wc -l
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.