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:
- ¿Puedo optimizar esto de alguna manera para acelerarlo?
- ¿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 master
directorio.
Las -z
opciones para sort
y tail
son necesarias, ya que la entrada está delimitada por nulos. Ninguno de los dos se quejará si hay menos de 50.000 líneas; sort
no le importa y tail
no generará nada, ya que no hay nada después de la línea 50.000. rm
podría quejarse de que se ejecuta sin argumentos, pero la -r
opción de GNU xargs
impedirá que se ejecute rm
si no recibe ninguna entrada (BSD xargs no lo necesita, pero probablemente no se quejará).
Por último, pero lo más importante, la -z
opció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