Exclua todos, exceto 1000 arquivos aleatórios em um diretório

13

Deixei que um script de geração de dados demorasse muito tempo e agora tenha mais de 200.000 arquivos, dos quais preciso reduzir para cerca de 1000. Na linha de comando do Linux, existe uma maneira fácil de excluir todos, exceto 1000 desses arquivos, onde os arquivos que seriam retidos não teria dependência do nome do arquivo ou de qualquer outro atributo?

Malcolm Regan
fonte
O processo que criou os arquivos tinha uma característica que relacionava cada arquivo ao anterior? Nesse caso, seria importante selecionar aleatoriamente para obter uma amostra representativa. Se o processo gerado arquivos que são aleatórios por natureza, você poderia tudo apenas de exclusão após a primeira 1000.
fixer1234

Respostas:

15

Exclua todos, exceto 1000 arquivos aleatórios em um diretório

Código:

find /path/to/dir -type f -print0 | sort -zR | tail -zn +1001 | xargs -0 rm

Explicação:

  1. Listar todos os arquivos /path/to/dircom find;
    • print0: use \0( caractere nulo ) como delimitador de linha; para que os caminhos de arquivo que contenham espaços / novas linhas não quebrem o script
  2. Embaralhe a lista de arquivos com sort;
    • -z: use \0(caractere nulo) como delimitador, em vez de \n(uma nova linha)
    • -R: ordem aleatória
  3. Retire as primeiras 1000 linhas da lista aleatória com tail;
    • -z: trate a lista como delimitada a zero (igual a sort)
    • -n +1001: mostra linhas a partir de 1001 (ou seja, omita as primeiras 1000 linhas)
  4. xargs -0 rm - remova os arquivos restantes;
    • -0: delimitado a zero, novamente

Por que é melhor que a solução do quixotic *:

  1. Funciona com nomes de arquivos contendo espaços / novas linhas.
  2. Não tenta criar nenhum diretório (que já pode existir, btw.)
  3. Não move nenhum arquivo, nem toca os 1000 "arquivos da sorte", além de listá-los find.
  4. Evita a falta de um arquivo, caso a saída de findnão termine com \n(nova linha) por algum motivo.

* - crédito para quixotesca para | sort -R | head -1000, me deu um ponto de partida.

rld.
fonte
Correndo no CentOS 6, eu estava recebendo erros sobre operandos inválidos. Felizmente eu não estou preocupado com espaços em filepaths assim remover os operandos trabalharam para mimfind . -type f | sort -R | tail -n +1001 | xargs rm
brad
@brad Você poderia fornecer as mensagens de erro e sua versão do find? Vou tentar melhorar minha resposta, só preciso de algumas sugestões para trabalhar.
rld.
3
tail: invalid option -- 'z'a versão do rabo que eu tenho é 8.4 #
brad
Eu acrescentaria---no-prazo se-vazio para xargs para erro evitada se não houver nenhum arquivo (após executá-lo duas vezes por exemple)
fraff
1

Use um diretório temporário, depois findtodos os seus arquivos, escolha a lista aleatoriamente sorte mova os 1000 principais da lista para o diretório temporário. Exclua o restante e mova os arquivos de volta do diretório temporário.

$ mkdir ../tmp-dir
$ find . -type f | sort -R | head -1000 | xargs -I "I" mv I ../tmp-dir/
$ rm ./*
$ mv ../tmp-dir/* .

Se xargsqueixa-se o comprimento da linha, usar um número menor com heade repetir o comando conforme necessário (isto é, a mudança -1000para -500e executá-lo duas vezes, ou alteração para -200e executá-lo 5 vezes).

Ele também falhará ao manipular nomes de arquivos que incluem espaços; como a resposta do @ rld mostra, você pode usar findo -print0argumento de, os -zargumentos para sorte heade -0com xargspara garantir o manuseio adequado do nome do arquivo.

Finalmente, se o tmp-dirjá existir, você deve substituir um nome de diretório que não existe.

quixotesco
fonte
Isso falhará se algum dos nomes de arquivos listados por findincluir um espaço.
rld.
0

Para usuários de mac, o seguinte script deve funcionar.

find . -type f -print0 | tr '\0' '\n' | sort -R | tail -n +10000 | tr '\n' '\0' | xargs -0 rm

trpermitirá que a classificação e a cauda trabalhem em listas com, em \nvez de \0.

Luca Di Liello
fonte
-2

O mais fácil pode ser rm -rf o diretório e, em seguida, execute novamente o script de geração de dados, certificando-se de não executar por muito tempo.

Lars Poulsen
fonte
Não foi isso que o OP pediu. Talvez fazer isso não seja viável.