Odpowiedzi:
Jeśli chcesz zapętlać pliki, nigdy nie używajls
*. tl; dr Istnieje wiele sytuacji, w których możesz usunąć niewłaściwy plik, a nawet wszystkie pliki.
To powiedziawszy, niestety jest to podstępna rzecz, którą należy zrobić dobrze w Bash. Jest to odpowiedź na pracę nad pomocą duplikatu pytanie mój nawet starszefind_date_sorted
, które można używać z małymi modyfikacjami:
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
* Bez przestępstw - użyłem też ls
wcześniej. Ale to naprawdę nie jest bezpieczne.
Edycja: Nowośćfind_date_sorted
z testami jednostkowymi.
((++counter>3))
jako swój test. Jest ładnie zwięzły. Jeśli chodzi o onelinerów: jeśli zwięzłość jest problemem, zawiń kod w funkcji, nie martw się o to.
Aby usunąć wszystkie oprócz 3 najnowszych plików za pomocą globu zsh, możesz użyć Om
(wielkich O) do sortowania plików od najstarszych do najnowszych oraz indeksu dolnego do przechwycenia żądanych plików.
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
Inne przykłady:
# 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])
Zdecydowanie najłatwiejszą metodą jest użycie zsh i jego globalnych kwalifikatorów : Om
sortowanie według malejącego wieku (tj. Najpierw najstarsze) i [1,3]
zachowanie tylko trzech pierwszych dopasowań.
rm ./*(Om[1,3])
Zobacz także Jak filtrować glob w Zsh, aby uzyskać więcej przykładów.
I postępuj zgodnie z radą L0B0 : Twój kod będzie strasznie pękał, jeśli będziesz mieć nazwy plików zawierające znaki specjalne powłoki.
Aby pobrać najnowszy plik z katalogu, możesz użyć następującej funkcji:
newest_in()
{
local newest=$1
for f;do [[ $f -nt $newest ]] && newest="$f"; done;
printf '%s\n' "$newest"
}
Daj mu inny zestaw plików, usuwając najnowszy plik po każdej iteracji.
Wskazówka: Jeśli trzymasz początkowy zestaw plików w tablicy o nazwie „$ {files [@]}”, zapisz indeks znalezionego najnowszego pliku i unset 'files[index]'
przed następną iteracją.
Stosowanie: newest_in [set of files/directories]
Przykładowe dane wyjściowe:
[rany$] newest_in ./*
foo.txt
[rany$]
Po pierwsze, -R
opcja dotyczy rekurencji, która prawdopodobnie nie jest tym, czego chcesz - będzie ona również wyszukiwać we wszystkich podkatalogach. Po drugie, <
operator (gdy nie jest postrzegany jako przekierowanie) służy do porównywania ciągów. Prawdopodobnie chcesz -lt
. Próbować:
while [ `ls -1A | grep ^- | wc -l` -lt 3 ]
Ale skorzystałbym z find tutaj:
while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]
Wiem, że parsowanie jest grzechemls
, ale co z tym:
find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm
Szybki test z 5 pustymi plikami:
$ >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
danych wyjściowych oraz niewłaściwego użycia find
i xargs
razem. Jeśli połączysz find
i xargs
polecam użyć opcji find
s -print0
i odpowiednio xargs
s -O
. Przeczytaj o używaniu Znajdź, aby uzyskać więcej informacji na temat. Możesz także rzucić okiem i przeczytać, dlaczego Parsing ls jest bardzo zły.
Ten jednowarstwowy robi wszystko, co myślę:
ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"
Oto jedno rozwiązanie:
rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)