Acelere la clasificación aleatoria y la eliminación (rm) para varios directorios

Acelere la clasificación aleatoria y la eliminación (rm) para varios directorios

Ejecutar MacOS en una terminal que es esencialmente BSD, por lo que publico mi pregunta aquí en lugar de hacer algo diferente. Quiero recortar mi conjunto de datos de imágenes en los pasos siguientes, eliminando archivos al azar. Algunos directorios tienen más de 1 millón de jpg. Mis datos están en el directorio maestro con subdirectorios que tienen solo una profundidad máxima de 1:

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

Encontré este enlace:

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

... y se le ocurrió:

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

Si bien funciona, me gustaría que lo hiciera de forma recursiva para los subdirectorios, de modo que no tenga que hacerlo manualmente para cada directorio. Entonces mis preguntas/solicitudes son:

  1. ¿Puedo optimizar esto de alguna manera para acelerarlo?
  2. ¿sort/tail devolverá un error cuando encuentre un directorio con menos de 50.000 archivos?

Respuesta1

Habiendo revisado la publicación fuente vinculada, parece que su bucle en realidad debería ser:

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

Se ejecutará desde el masterdirectorio.

Las -zopciones para sorty tailson necesarias, ya que la entrada está delimitada por nulos. Ninguno de los dos se quejará si hay menos de 50.000 líneas; sortno le importa y tailno generará nada, ya que no hay nada después de la línea 50.000. rmpodría quejarse de que se ejecuta sin argumentos, pero la -ropción de GNU xargsimpedirá que se ejecute rmsi no recibe ninguna entrada (BSD xargs no lo necesita, pero probablemente no se quejará).

Por último, pero lo más importante, la -zopción de entrada delimitada por nulos probablemente no será compatible con BSD tail. Necesitaría la cola GNU, que se puede instalar usando homebrew.

Probablemente podría prescindir de las líneas delimitadas por nulos, si se garantiza que sus nombres de archivos no tendrán espacios, nuevas líneas, comillas, barras invertidas, etc. En ese caso:

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

información relacionada