Los problemas con las respuestas existentes:
- incapacidad para manejar nombres de archivo con espacios o saltos de línea embebidos.
- en el caso de las soluciones que invocan
rm
directamente en una sustitución de orden sin comillas (rm `...`
), hay un riesgo añadido de englobamiento no deseado.
- incapacidad para distinguir entre los archivos y directorios (es decir, si ocurrieron directorios para estar entre los 5 elementos del sistema de archivos más recientemente modificados, que le retiene con eficacia menos que 5 archivos, y aplicando
rm
a directorios fallar).
wnoise's answer direcciones de estas cuestiones, pero la solución es GNU específico de (y bastante complejo).
he aquí una solución pragmática, compatible con POSIX que viene con solamente una advertencia: no puede manejar nombres de archivo con incrustados nuevas líneas - pero yo no considero que una preocupación en el mundo real para la mayoría de la gente.
Para el registro, aquí está la explicación de por qué no es generalmente una buena idea para analizar ls
de salida: http://mywiki.wooledge.org/ParsingLs
ls -tp | grep -v '/$' | tail -n +6 | xargs -I {} rm -- {}
Lo anterior es ineficiente, porque xargs
tiene que invocar rm
una vez para cada nombre de archivo.
de xargs
puede permitir que usted para solucionar este problema su plataforma:
Si tiene GNUxargs
, utilice -d '\n'
, lo que hace xargs
consideran cada línea de entrada un argumento separado, sin embargo, pasa a tantos argumentos como quepan en una línea de comandos a la vez :
ls -tp | grep -v '/$' | tail -n +6 | xargs -d '\n' -r rm --
-r
(--no-run-if-empty
) asegura que rm
no se invoca si no hay entrada.
Si tiene BSDxargs
(incluyendo el OS X), se puede utilizar para manejar -0
NUL
de entrada Separado, después de traducir primero a las nuevas líneas NUL
(0x0
) caracteres., Que también pasa (normalmente) todos los ficheros a la vez (también trabajará con GNU xargs
):
ls -tp | grep -v '/$' | tail -n +6 | tr '\n' '\0' | xargs -0 rm --
Explicación:
ls -tp
grabados los nombres de los elementos del sistema de archivos ordenados por cuánto tiempo hace que se modificaron, en orden descendente (modificado más recientemente artículos primero) (-t
), con directorios impresos con un trailing /
para marcarlos como tal (-p
).
grep -v '/$'
elimina los directorios de la lista resultante, omitiendo (-v
) líneas que tienen un /
posterior (/$
).
- Advertencia: Desde un enlace simbólico que apunta a un directorio técnicamente no es en sí un directorio, se no ser excluidos dichos enlaces simbólicos.
tail -n +6
se salta los primeros 5 entradas en el perfil, en efecto, devolver todos los pero los 5 archivos más recientemente modificados, en su caso.
Tenga en cuenta que para excluir los archivos N
, N+1
debe pasarse a xargs -n +
.
xargs -I {} rm -- {}
(y sus variaciones) luego invoca en rm
en todos estos archivos; si no hay ninguna coincidencia, xargs
no hará nada.
xargs -I {} rm -- {}
define marcador de posición {}
que representa cada línea de entrada como un todo, de modo rm
es entonces invocado una vez por cada línea de entrada, pero con nombres de archivo con espacios incrustados se maneja correctamente.
--
en todos los casos se asegura de que los nombres de archivo que le suceden a comenzar con -
no se confundan con las opciones por rm
.
A variación en el problema original, en caso de que los archivos coincidentes necesitan ser procesados individualmente o recogió en una matriz de cáscara:
# One by one, in a shell loop (POSIX-compliant):
ls -tp | grep -v '/$' | tail -n +6 | while IFS= read -r f; do echo "$f"; done
# One by one, but using a Bash process substitution (<(...),
# so that the variables inside the `while` loop remain in scope:
while IFS= read -r f; do echo "$f"; done < <(ls -tp | grep -v '/$' | tail -n +6)
# Collecting the matches in a Bash *array*:
IFS=$'\n' read -d '' -ra files < <(ls -tp | grep -v '/$' | tail -n +6)
printf '%s\n' "${files[@]}" # print array elements
Sin duda mejor que la mayoría de las otras respuestas aquí, así que estoy feliz de prestar mi apoyo, incluso en la medida en que considero ignorar el caso de nueva línea como algo que debe hacerse solo con precaución . –
Excelente respuesta. ¿Qué sucede si quiero poner todos los archivos a eliminar en una matriz y procesarlos en un bucle for? (El tiempo de procesamiento no es un problema aquí.) – Bulrush
Si '' ls' no está en el directorio actual, las rutas a los archivos contendrán '/', lo que significa que 'grep -v '/'' no coincidirá con nada . Creo que 'grep -v '/ $'' es lo que quieres excluir solo directorios. – waldol1