Analisando a saída de ls não é confiável .
Em vez disso, use find para localizar os diretórios e sort para encomendá-los por timestamp. Por exemplo:
IFS= read -r -d $'#!/usr/bin/env bash
dir="$1"
min_dirs=3
[[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] &&
IFS= read -r -d $'IFS= read -r -d $'#!/usr/bin/env bash
dir="$1"
min_dirs=3
[[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] &&
IFS= read -r -d $'%pre%' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p%pre%' 2>/dev/null | sort -z -n)
file="${line#* }"
ls -lLd "$file"
' line < <(find . -maxdepth 1 -type d -printf '%T@ %p%pre%' \
2>/dev/null | sort -z -n)
file="${line#* }"
# do something with $file here
' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p%pre%' 2>/dev/null | sort -z -n)
file="${line#* }"
ls -lLd "$file"
' line < <(find . -maxdepth 1 -type d -printf '%T@ %p%pre%' \
2>/dev/null | sort -z -n)
file="${line#* }"
# do something with $file here
O que tudo isso está fazendo?
Primeiro, os comandos find localizam todos os diretórios no diretório atual ( . ), mas não nos subdiretórios do diretório atual ( -maxdepth 1 ), depois imprimem:
- Um registro de data e hora
- Um espaço
- O caminho relativo para o arquivo
- Um caractere NULL
O registro de data e hora é importante. O %T@ do especificador de -printf divide em T , o que indica "Hora da última modificação" do arquivo (mtime) e @ , que indica "Segundos desde 1970", incluindo os segundos fracionários.
O espaço é meramente um delimitador arbitrário. O caminho completo para o arquivo é para que possamos nos referir a ele mais tarde, e o caractere NULL é um terminador porque é um caractere ilegal em um nome de arquivo e, portanto, nos informa com certeza que chegamos ao final do caminho para o arquivo. arquivo.
Eu incluí o 2>/dev/null para que os arquivos que o usuário não tem permissão para acessar sejam excluídos, mas as mensagens de erro sobre eles serem excluídos sejam suprimidas.
O resultado do comando find é uma lista de todos os diretórios no diretório atual. A lista é canalizada para sort , que é instruído para:
-
-zTrate NULL como o caractere terminador de linha em vez de nova linha. -
-nOrdenar numericamente
Como os segundos desde 1970 sempre sobem, queremos o arquivo cujo registro de data e hora seja o menor número. O primeiro resultado de sort será a linha que contém o menor registro de data e hora numerado. Tudo o que resta é extrair o nome do arquivo.
Os resultados do find , sort pipeline são transmitidos por meio de substituição de processos para read , onde é lido como se fosse um arquivo em stdin.
No contexto de read , definimos a variável IFS como nada, o que significa que o espaço em branco não será interpretado de forma inadequada como um delimitador. read é informado -r , que desativa a expansão de escape, e -d $' , que torna o delimitador de fim de linha NULL, correspondendo à saída de nosso find'sort , line pipeline.
O primeiro bloco de dados, que representa o caminho do diretório mais antigo precedido por seu registro de data e hora e espaço, é lido na variável #* . Em seguida, a substituição de parâmetros é usada com a expressão $file , que simplesmente substitui todos os caracteres do início da string até o primeiro espaço, incluindo o espaço, sem nada. Isso remove o registro de data e hora da modificação, deixando apenas o caminho completo para o arquivo.
Neste ponto, o nome do arquivo é armazenado em rm -rf "$file" e você pode fazer o que quiser com ele, incluindo ls -t .
Não existe uma maneira mais simples?
Não. Formas mais simples são bugs.
Se você usar tail e pipe para rm $(anything) , você quebrará arquivos com novas linhas nos nomes dos arquivos. Se você rm "$(anything)" , os arquivos com espaço em branco no nome causarão a quebra. Se você %code% , os arquivos com novas linhas no nome causarão quebra.
Talvez, em casos específicos, você tenha certeza de que uma maneira mais simples é suficiente, mas nunca deve escrever suposições como essa em scripts, se puder evitar fazê-lo.
Editar
%pre%Uma solução mais completa para o problema, pois ele verifica primeiro a contagem de diretórios.