remove o arquivo, mas exclui todos os arquivos de uma lista

15

Eu preciso limpar uma pasta periodicamente. Eu recebo uma lista de arquivos que contém texto, quais arquivos são permitidos. Agora eu tenho que apagar todos os arquivos que não estão neste arquivo.

Exemplo:

dont-delete.txt :

dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt

Minha pasta de limpeza contém isso como exemplo:

ls /home/me/myfolder2tocleanup/ :

dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt
this-can-be-deleted.txt
also-waste.txt
never-used-it.txt

Portanto, esses arquivos devem ser excluídos:

this-can-be-deleted.txt
also-waste.txt
never-used-it.txt

Eu pesquiso algo para criar um comando delete com uma opção para excluir alguns arquivos fornecidos pelo arquivo.

    
por stefan83 28.09.2016 / 16:39

7 respostas

5

O comando rm está comentado para que você possa verificar e verificar se está funcionando conforme necessário. Então apenas descomente essa linha.

A seção check directory garantirá que você não execute o script acidentalmente no diretório errado e destrua os arquivos incorretos.

Você pode remover a linha echo deleting para ser executada silenciosamente.

#!/bin/bash

cd /home/me/myfolder2tocleanup/

# Exit if the directory isn't found.
if (($?>0)); then
    echo "Can't find work dir... exiting"
    exit
fi

for i in *; do
    if ! grep -qxFe "$i" filelist.txt; then
        echo "Deleting: $i"
        # the next line is commented out.  Test it.  Then uncomment to removed the files
        # rm "$i"
    fi
done
    
por L. D. James 28.09.2016 / 17:32
10

Este script python pode fazer isso:

#!/usr/bin/env python3
import os
no_remove = set()
with open('./dont-delete.txt') as f:
     for line in f:
         no_remove.add(line.strip())

for f in os.listdir('.'):
    if f not in no_remove:
        print('unlink:' + f ) 
        #os.unlink(f)

A parte importante é descomentar a função os.unlink() .

NOTE : adicione este script e dont-delete.txt ao seu dont-delete.txt para que ambos estejam na lista e mantenha-os no mesmo diretório.

    
por Sergiy Kolodyazhnyy 28.09.2016 / 16:53
3

Aqui está um verso:

comm -2 -3 <(ls) <(sort dont_delete) | tail +2 | xargs -p rm
  1. ls imprime todos os arquivos no diretório atual (na ordem de classificação)
  2. sort dont_delete imprime todos os arquivos que não queremos excluir na ordem de classificação
  3. o operador <() transforma uma string em um objeto semelhante a um arquivo
  4. Os comandos comm comparam dois arquivos pré-classificados e imprimem linhas em que eles diferem
  5. usar as -2 -3 flags faz com que comm imprima apenas as linhas contidas no primeiro arquivo, mas não no segundo, que será a lista de arquivos que podem ser excluídos com segurança
  6. a chamada tail +2 é apenas para remover o título da comm output, que contém o nome do arquivo de entrada
  7. Agora, temos uma lista de arquivos para excluir no padrão. Nós canalizamos essa saída para xargs , o que transformará o fluxo de saída em uma lista de argumentos para rm . A opção -p força xargs a pedir confirmação antes de executar.
por gardenhead 29.09.2016 / 04:47
1

FWIW parece que você pode fazer isso nativamente em zsh , usando o qualificador (+cmd) glob.

Para ilustrar, vamos começar com alguns arquivos

 % ls
bar  baz  bazfoo  keepfiles.txt  foo  kazoo

e um arquivo de lista de permissões

 % cat keepfiles.txt
foo
kazoo
bar

Primeiro, leia a lista de permissões em uma matriz:

 % keepfiles=( "${(f)$(< keepfiles.txt)}" )

ou talvez melhor

 % zmodload zsh/mapfile
 % keepfiles=( ${(f)mapfile[./keepfiles.txt]} )

(o equivalente do bash mapfile builtin - ou seu sinônimo readarray ). Agora podemos verificar se existe uma chave (nome do arquivo) na matriz usando ${keepfiles[(I)filename]} , que retorna 0 se nenhuma correspondência for encontrada:

 % print ${keepfiles[(I)foo]}
1
 % print ${keepfiles[(I)baz]}
0
 %

Podemos usar isso para fazer uma função que retorna true se não houver correspondências para $REPLY na matriz:

% nokeep() { (( ${keepfiles[(I)$REPLY]} == 0 )); }

Finalmente, usamos essa função como um qualificador em nosso comando:

 % ls *(+nokeep)
baz  bazfoo  keepfiles.txt

ou, no seu caso

 % rm -- *(+nokeep)

(Você provavelmente vai querer adicionar o nome do arquivo whitelist à lista de permissões.)

    
por steeldriver 28.09.2016 / 21:03
0

Assumindo que seu shell bash tenha o extglob shopt definido como ativado, aqui está uma alternativa um pouco mais conservadora:

rm !($(tr \n \| < keep.txt))

(... acompanhando a excelente sugestão de comunicação do @ gardenhead!)

    
por conny 29.09.2016 / 10:35
0

Supondo que não há espaços em branco (Espaços / Tabs) nos seus arquivos 'listados em um arquivo chamado list , então você faria:

find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \)

Basta adicionar -delete ao comando acima para excluir os arquivos que não existem no arquivo lista . Se a sua descoberta não tiver a opção -delete , você poderá usar rm com -exec da seguinte forma:

find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \) -exec echo rm {} \;

Ou usando -exec com + terminator .

find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \) -exec echo rm {} +

echo é usado apenas para execução a seco.

    
por αғsнιη 18.04.2018 / 13:27
0

Meu one-liner é:

find . -type f -print | grep -Fxvf dont-delete.txt | xargs -d'\n' rm
    
por nyxz 31.05.2018 / 18:35