Exclua a pasta mais antiga de um caminho com uma exclusão

1

Eu mencionei o seguinte tópico Como excluir o diretório mais antigo em um determinado diretório? e a solução aceita é perfeita. No entanto, tenho um requisito para isentar uma pasta que é a mais antiga. Como posso acomodar esse requisito na solução fornecida?

    
por Rajesh Thampi 30.09.2018 / 07:59

5 respostas

0

Você pode adaptar a solução original para ler arquivos até encontrar um que não esteja excluído:

while IFS= read -r -d '' line
do
    file="${line#* }"
    if [ "$file" = './my-excluded-directory' ]
    then
        continue
    fi
    [do stuff with $file]
    break
done < <(find . -maxdepth 1 -type d -printf '%T@ %p
IFS= read -r -d '' < <(find . -maxdepth 1 -type d \( -name 'my-excluded-directory' -prune -false \) -o -printf '%T@ %p
while IFS= read -r -d '' line
do
    file="${line#* }"
    if [ "$file" = './my-excluded-directory' ]
    then
        continue
    fi
    [do stuff with $file]
    break
done < <(find . -maxdepth 1 -type d -printf '%T@ %p
IFS= read -r -d '' < <(find . -maxdepth 1 -type d \( -name 'my-excluded-directory' -prune -false \) -o -printf '%T@ %p%pre%' | sort -z -n)
file="${REPLY#* }"
# do something with $file here
' | sort -z -n)
' | sort -z -n) file="${REPLY#* }" # do something with $file here
' | sort -z -n)

( -d '' é equivalente ao original, porque você não pode ter caracteres NUL em strings.)

read ing uma longa lista é lenta, e mosvy está certo que você pode fazer a filtragem com uma sintaxe find bastante desagradável:

%pre%     
por 30.09.2018 / 09:17
0

Uma forma "prática" de fazer isso seria alterar o registro de data e hora do diretório excluído no início e restaurar seu registro de data e hora no final:

$ cd "$(mktemp --directory)"
$ echo foo > example.txt
$ modified="$(date --reference=example.txt +%s)" # Get its original modification time
$ touch example.txt # Set the modification time to now
[delete the oldest file]
$ touch --date="@$modified" example.txt # Restore; the "@" denotes a timestamp

Advertências usuais são aplicáveis:

  • Isso não restaurará o timestamp original se for eliminado antes de ser concluído (ou em caso de perda de energia, etc.). Se for realmente importante restaurar o registro de data e hora, você poderá usar touch --reference="$path" "${path}.timestamp" para salvar o registro de data e hora em um arquivo real e restaurar usando touch --reference="${path}.timestamp" "$path" .
  • Os nomes das opções são baseados em coretools GNU. Você pode ter que usar nomes de opções menos legíveis para fazer a mesma coisa em outros * nixes.
por 30.09.2018 / 09:10
0

com zsh :

set -o extendedglob # best in ~/.zshrc
rm -rf -- ^that-folder-to-keep(D/Om[1])

Com a solução fornecida em outro Q & A:

IFS= read -r -d '' line < <(
  find . -maxdepth 1 \
    ! -name that-folder-to-keep \
    -type d -printf '%T@ %p
rm -rf -- *(D/Om[2])
' 2>/dev/null | sort -z -n) && rm -rf "${line#* }"

Se você deseja remover o segundo mais antigo:

zsh :

{ IFS= read -r -d '' line &&
  IFS= read -r -d '' line &&; } < <(
  find . -maxdepth 1 \
    -type d -printf '%T@ %p
set -o extendedglob # best in ~/.zshrc
rm -rf -- ^that-folder-to-keep(D/Om[1])
' 2>/dev/null | sort -z -n) && rm -rf "${line#* }"

Utilitários GNU:

IFS= read -r -d '' line < <(
  find . -maxdepth 1 \
    ! -name that-folder-to-keep \
    -type d -printf '%T@ %p
rm -rf -- *(D/Om[2])
' 2>/dev/null | sort -z -n) && rm -rf "${line#* }"
    
por 30.09.2018 / 09:28
0

Não, essa solução não é perfeita, porque depende de muitos recursos altamente não portáteis ( find -printf , sort -z , read -d , etc).

Minha solução também não é perfeita, pois depende do operador -ot de test (que testa se um arquivo é mais antigo que outro); no entanto, parece ser muito melhor suportado (* bsd, busybox, solaris, linux).

# usage with_2nd_oldest 'command' files ...
with_2nd_oldest(){
        cmd="$1"; shift
        oz="$1"; shift; oy=$1
        for f; do
                if [ "$f" -ot "$oz" ]; then oy=$oz oz=$f
                elif [ "$f" -ot "$oy" -a "$f" != "$oz" ]; then oy=$f
                fi
        done
        $cmd "$oy"
}
$ with_2nd_oldest 'echo rm -fr --' dir/*/

Isso também é capaz de lidar com argumentos duplicados:

$ for i in 'seq 1 9'; do mkdir -p $i; sleep 1; done
$ with_2nd_oldest echo 7 7 1 1 3 3 2 2 8 9 5 1
2

Para a outra pergunta mais antiga, em que o arquivo / diretório mais antigo era necessário, é ainda mais simples:

with_oldest(){
        cmd="$1"; shift
        oz="$1"; shift
        for f; do test "$f" -ot "$oz" && oz=$f; done
        $cmd "$oz"
}

Ambos podem ser facilmente adaptados para ignorar caminhos arbitrários ou para ler a lista de arquivos do stdin.

    
por 30.09.2018 / 09:18
0
#!/bin/bash
while IFS= read -r -d '' line
do
    file="${line#* }"
    if [ "$file" = './Development_Instance' ]
    then
        continue
fi

if [ "$file" = './lost+found' ]
then
continue
fi
    echo $file
    break
done < <(find . -maxdepth 1 -type d -printf '%T@ %p
#!/bin/bash
while IFS= read -r -d '' line
do
    file="${line#* }"
    if [ "$file" = './Development_Instance' ]
    then
        continue
fi

if [ "$file" = './lost+found' ]
then
continue
fi
    echo $file
    break
done < <(find . -maxdepth 1 -type d -printf '%T@ %p%pre%' | sort -z -n)
' | sort -z -n)

Foi assim que eu consegui. Eu sei que não é a maneira elegante de fazer isso. Apenas faz a coisa por mim.

    
por 30.09.2018 / 13:14