Eu sugeriria outra solução, que andará recursivamente dentro da estrutura da árvore de diretórios de destino e excluirá todos os arquivos, exceto um número predefinido dos novos arquivos. Essa solução é baseada em: (1) Script bash recursivo e (2) Explicando um script de shell para imprimir recursivamente a árvore de diretórios completa .
1. Crie um arquivo de script executável, chamado walkr
( caminhar e remover ), localizado em /usr/local/bin
para ser acessível como comando shell ( etapas mais detalhadas ).
2. O conteúdo do script walkr
é bastante simples:
#!/bin/bash
[[ -z "${NFK}" ]] && NFK='7' || NFK="$NFK"
[[ -z "" ]] && ABS_PATH="${PWD}" || cd "" && ABS_PATH="${PWD}"
file_operations() {
local IFS=$'\t\n' # Change the value of the Internal Field Separator locally
rm $(ls -lt | grep -Po '^-.*[0-9]{2}:[0-9]{2} \K.*' | tail -n +"$((NFK+1))") 2>/dev/null
}
walk() {
cd "" && file_operations # Change directory to the destination path and call the above function
for item in ""/*; do [[ -d "$item" ]] && walk "$item"; done # Make the recursion
}
walk "${ABS_PATH}"
3. Explicação:
-
No início, o script verificará se a variável $NFK
(que determina o número de arquivos a serem mantidos) é definida antecipadamente - a condição [[ -z "${NFK}" ]]
. Se não estiver definido, o valor padrão será 7
.
-
Em seguida, o script lida com o caminho de destino (stdin do comando). Se não for fornecido - a condição [[ -z "" ]]
- o script funcionará no diretório atual.
-
Finalmente, a função principal walk()
será executada.
4. Exemplos de uso:
-
Para executar walkr
no diretório atual:
walkr # You shouldn't use any argument,
walkr ./ # but you can use also this format
-
Para executar walkr
em qualquer diretório filho:
walkr <directory name>
walkr ./<directory name>
walkr <directory name>/<sub directory>
-
Para executar walkr
para qualquer outro diretório:
walkr /full/path/to/<directory name>
-
Para alterar o número de arquivos a serem mantidos (para 3
, por exemplo), use este formato
NFK=3 walkr
NFK=3 walkr /full/path/to/<directory name>
# etc.
5. Vamos brincar com o script walkr
:
-
Podemos usar o comando touch file.name -d "1 hour ago"
para criar um arquivo vazio com a data de uma hora atrás. Assim, podemos usar os seguintes comandos para criar uma estrutura de diretórios como esta apresentada aqui .
mkdir -p ~/temp/dir{A..C} && cd ~/temp ;\
DEST=''; touch ${DEST}new_file{1..7} && touch ${DEST}older_file{1..7} -d "1 hour ago" && touch ${DEST}oldest_file{1..7} -d "2 hour ago" ;\
DEST='dirA/'; touch ${DEST}new_file{1..7} && touch ${DEST}older_file{1..7} -d "1 hour ago" && touch ${DEST}oldest_file{1..7} -d "2 hour ago" ;\
DEST='dirB/'; touch ${DEST}new_file{1..7} && touch ${DEST}older_file{1..7} -d "1 hour ago" && touch ${DEST}oldest_file{1..7} -d "2 hour ago" ;\
DEST='dirC/'; touch ${DEST}new_file{1..7} && touch ${DEST}older_file{1..7} -d "1 hour ago" && touch ${DEST}oldest_file{1..7} -d "2 hour ago"
-
Agora podemos realizar alguns testes:
Atualização da funcionalidade do script. Aqui é apresentada a versão atualizada do script acima:
#!/bin/bash
[[ -z "" ]] && ABS_PATH="${PWD}" || cd "" && ABS_PATH="${PWD}"
[[ -z "" ]] && NFK='7' || NFK="" # Number of the files to be kept
[[ -z "" ]] && REC='1' || REC="" # REC='1' - work recursively
[[ -z "" ]] && VRB='1' || VRB="" # VRB='1' - work in verbose mode
file_operations() {
local IFS=$'\t\n' # Change the value of the Internal Field Separator locally
if [ "$VRB" == "1" ]
then # Verbose mode:
rm -v $(ls -lt | grep -Po '^-.*[0-9]{2}:[0-9]{2} \K.*' | tail -n +"$((NFK+1))") 2>/dev/null && printf " -from: '%s' \n" "" || echo "nothing to remove in: ''"
else # Quiet mode:
rm $(ls -lt | grep -Po '^-.*[0-9]{2}:[0-9]{2} \K.*' | tail -n +"$((NFK+1))") 2>/dev/null
fi
}
walk() {
# Change directory to the destination path and call the above function, pass for the verbose mode
cd "" && file_operations ""
# If REC='1': Recursive mode -- Make the recursion; otherwise work on the curent level
if [ "$REC" == "1" ]; then for item in ""/*; do [[ -d "$item" ]] && walk "$item"; done; fi
}
walk "${ABS_PATH}"
-
Esta versão do script pode lidar com mais algumas variáveis de entrada. Ele tem os modos quiet e verbose e pode funcionar de forma não recursiva.
-
O formato completo é:
walkr '<destination path>' '<number of lines to be kept>' '<no recursion>' '<quiet>'
Onde o conteúdo exato de <no recursion>
e <quiet>
não tem importância. Apenas as variáveis de entrada
e
não devem estar vazias para serem sobrescritas pelo comportamento padrão.