xóa các tập tin cũ nhất


9

Tôi đang cố xóa các tệp cũ khỏi thư mục và chỉ để lại 3 tệp mới nhất.

cd /home/user1/test

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

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

done

có gì đó không đúng với tuyên bố có điều kiện.

Câu trả lời:


9

Nếu bạn muốn lặp qua các tập tin, không bao giờ sử dụngls *. tl; dr Có rất nhiều tình huống cuối cùng bạn xóa tệp sai hoặc thậm chí tất cả các tệp.

Điều đó nói rằng, thật không may, đây là một điều khó khăn để làm ngay trong Bash. Có một câu trả lời làm việc tại một câu hỏi trùng lặp thậm chí cũ hơnfind_date_sorted mà bạn có thể sử dụng với các sửa đổi nhỏ:

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

* Không có kẻ xúc phạm - Tôi cũng đã sử dụng lstrước đây. Nhưng nó thực sự không an toàn.

Chỉnh sửa: Mớifind_date_sorted với các bài kiểm tra đơn vị.


Tôi thứ hai phần về không phân tích ls. Ngoài ra kịch bản gọn gàng nhưng tôi nghĩ nó có thể được thực hiện trong một lớp lót, hãy để tôi kiểm tra ...
rahmu

Chà, bạn luôn có thể nén mã Bash thành một lớp lót, nhưng vấn đề là liệu nó có đọc được không :)
l0b0

2
Nếu tôi có thể đánh cắp một ý tưởng không thương tiếc từ @ Peter.O, hãy thử ((++counter>3))làm bài kiểm tra của bạn. Nó gọn gàng độc đáo. Đối với oneliners: Nếu sự ngắn gọn là một mối quan tâm bao bọc mã trong một hàm, thì đừng lo lắng về nó.
Sorpigal

Phím tắt @Sorpigal Neat
l0b0

5

Để xóa tất cả trừ 3 tệp mới nhất bằng zsh global, bạn có thể sử dụng Om(viết hoa O) để sắp xếp các tệp từ cũ nhất đến mới nhất và một chỉ mục để lấy các tệp bạn muốn.

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

Những ví dụ khác:

# 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

Cho đến nay, phương pháp đơn giản nhất là sử dụng zsh và vòng loại toàn cầu của nó : Omsắp xếp theo độ tuổi giảm (tức là già nhất trước) và [1,3]chỉ giữ lại ba trận đấu đầu tiên.

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

Xem thêm Làm thế nào để tôi lọc một quả cầu trong zsh để biết thêm ví dụ.

Và hãy chú ý lời khuyên của l0b0 : mã của bạn sẽ bị hỏng khủng khiếp nếu bạn có tên tệp chứa các ký tự đặc biệt.


Woa woa giữ tàu, đây thực sự là một giải pháp hoàn chỉnh trong 1 dòng?
MetaGuru

2
@Ryan Đó là zsh cho bạn.
Gilles 'SO- ngừng trở nên xấu xa'

1

Bạn có thể sử dụng chức năng sau để lấy tệp mới nhất trong một thư mục:

newest_in() 
{ 
    local newest=$1

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

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

Cung cấp cho nó một tập hợp các tệp khác nhau bằng cách loại bỏ tệp mới nhất sau mỗi lần lặp.

Mẹo: Nếu bạn giữ tập hợp tệp ban đầu trong một mảng có tên là "$ {files [@]}", thì hãy lưu chỉ mục của tệp mới nhất được tìm thấy và unset 'files[index]'trước lần lặp tiếp theo.

Sử dụng: newest_in [set of files/directories]

Đầu ra mẫu:

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

-1

Đầu tiên, -Rtùy chọn dành cho đệ quy, có lẽ không phải là điều bạn muốn - điều đó cũng sẽ tìm kiếm trong tất cả các thư mục con. Thứ hai, <toán tử (khi không được xem là chuyển hướng) là để so sánh chuỗi. Bạn có thể muốn -lt. Thử:

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

Nhưng tôi sẽ sử dụng tìm ở đây:

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

Cả hai sẽ thất bại nếu một hoặc nhiều tên tệp chứa '$ \ n'.
Rany Albeg Wein

-1

Tôi biết đó là một tội lỗi để phân tích ls, nhưng những gì về điều này:

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

Một thử nghiệm nhanh với 5 tệp trống:

$ >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

Điều này sẽ thất bại vì hai lý do - Phân tích lsđầu ra và sử dụng findxargscùng nhau sai cách. Nếu bạn kết hợp findxargstôi khuyên bạn nên sử dụng tùy chọn finds -print0và theo xargsđó -O. Đọc về Sử dụng Tìm để biết thêm thông tin về chủ đề. Bạn cũng có thể muốn xem và đọc về lý do tại sao Parsing ls rất tệ.
Rany Albeg Wein

-2

Điều này một lót làm tất cả những gì tôi nghĩ:

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

ls là một công cụ để tương tác xem thông tin tập tin. Đầu ra của nó được định dạng cho con người và sẽ gây ra lỗi trong các tập lệnh. Sử dụng quả cầu hoặc tìm thay thế. Hiểu lý do tại sao: mywiki.wooledge.org/ParsingLs
Rany Albeg Wein

-2

Đây là một giải pháp:

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

1
@bakbak ls là một công cụ để tương tác xem thông tin tệp. Đầu ra của nó được định dạng cho con người và sẽ gây ra lỗi trong các tập lệnh. Nhìn vào đây để hiểu tại sao . Nói cụ thể về câu trả lời của bạn - câu hỏi này sẽ bị hỏng nếu một hoặc nhiều tệp chứa ký tự $ '\ n'. Ngoài ra, Thay thế lệnh (ví dụ $ (...)) thiếu dấu ngoặc kép, điều này dẫn đến một chủ đề quan trọng khác - Chia tách từ !
Rany Albeg Wein
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.