Acelere a classificação e exclusão aleatória (rm) para vários diretórios

Acelere a classificação e exclusão aleatória (rm) para vários diretórios

Executando MacOS em um terminal que é essencialmente BSD, por isso postei minha pergunta aqui em vez de perguntar diferente. Quero reduzir meu conjunto de dados de imagem nas etapas subsequentes, excluindo arquivos aleatoriamente. Alguns diretórios têm mais de 1 milhão de jpgs. Meus dados estão no diretório mestre com subdiretórios com profundidade máxima de apenas 1:

-master
     -data1
       image.jpgs
     -data2
       image.jpgs
     -data3
       image.jpgs
     -data4
       image.jpgs
... and so forth

Encontrei este link:

https://superuser.com/questions/1186350/delete-all-but-1000-random-files-in-a-directory

... e surgiu com:

for f in *.jpg; do find "$f" -type f -print0 | sort -R | tail -n +50001 | xargs -0 rm; done

Embora funcione, gostaria que fizesse isso recursivamente para subdiretórios, para não precisar fazer isso manualmente para cada diretório. Então, minhas perguntas/solicitações são:

  1. Posso otimizar isso de alguma forma para acelerar?
  2. O sort/tail retornará um erro quando encontrar um diretório com menos de 50.000 arquivos?

Responder1

Depois de verificar a postagem de origem vinculada, parece que seu loop deveria ser:

for d in */; do find "$d" -iname '*.jpg' -type f -print0 | sort -zR | tail -zn +50001 | xargs -0r rm; done

Para ser executado a partir do masterdiretório.

As -zopções para sorte tailsão necessárias, pois a entrada é delimitada por nulos. Nenhum dos dois reclamará se houver menos de 50.000 linhas - sortnão se importa e tailnão produzirá nada, já que não há nada após a 50.000ª linha. rmpode reclamar de ser executado sem argumentos, mas a -ropção GNU xargsimpedirá sua execução rmse não receber nenhuma entrada (BSD xargs não precisa disso, mas provavelmente não reclamará).

Por último, mas mais importante, a -zopção para entrada delimitada por nulos provavelmente não será suportada pelo BSD tail. Você precisaria do GNU tail, que pode ser instalado usando o homebrew.

Você provavelmente poderia ficar sem linhas delimitadas por nulos, se for garantido que seus nomes de arquivos não contenham espaços, novas linhas, aspas, barras invertidas, etc. Nesse caso:

for d in */; do find "$d" -type f | sort -R | tail -n +50001 | xargs rm; done

informação relacionada