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:
- Posso otimizar isso de alguma forma para acelerar?
- 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 master
diretório.
As -z
opções para sort
e tail
são necessárias, pois a entrada é delimitada por nulos. Nenhum dos dois reclamará se houver menos de 50.000 linhas - sort
não se importa e tail
não produzirá nada, já que não há nada após a 50.000ª linha. rm
pode reclamar de ser executado sem argumentos, mas a -r
opção GNU xargs
impedirá sua execução rm
se não receber nenhuma entrada (BSD xargs não precisa disso, mas provavelmente não reclamará).
Por último, mas mais importante, a -z
opçã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