Me gustaría saber todos los archivos que tienen más de 100 Mb y a los que no se ha accedido en el último mes, y he escrito con éxito:
find / -size +100M -atime +30
Y ahora quiero mover esos archivos a una carpeta llamada /big-not-used cambiando su nombre como: file_nameYYYYMMDD
donde nombre_archivo es el nombre del archivo original y AAAAMMDD es la fecha de hoy, en año mes día. Por ejemplo film.mkv
va a/big-not-used/film.mkv20161031
Mi frase sería:
find / -size +100M -atime +30 -exec mv {} /big-not-used/... \;
Pero no sé cómo agregar la fecha de hoy al nombre del archivo. He descubierto que date +%Y-%m-%d
los resultados son: 2016-10-31
lo cual es útil. Ahora la duda es ¿cómo obtener el nombre de este archivo? Siguiente:
https://stackoverflow.com/questions/5456120/how-to-only-get-file-name-with-linux-find
... -exec basename {} \;
¿Tal vez?:
find / -size +100M -atime +30 -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;
Pero da un error porque el nombre base responde con la ruta completa del archivo en lugar del nombre que yo usaría:
${var##/*/}
para obtener el nombre del archivo, pero la pregunta es ¿cómo inserto las basename {}
respuestas en la var en la expresión anterior?
¿Tal vez?
$(${$(basename {})##/*/})
Pero dice error sintáctico cerca del inesperado '}'...
Respuesta1
Te estabas acercando a:
find / -size +100M -atime +30 \
-exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;
Pero sin citar, la expansión del caparazón de $(...)
las construcciones ocurreantes de que se ejecute el find
comando. En otras palabras, dada la línea de comando anterior, lo que realmente se ejecuta es:
find / -size +100M -atime +30 \
-exec mv {} /big-not-used/{}2016-10-30 \;
Porque el resultado de $(basename {})
es solo {}
y es por eso que terminas con la ruta completa. Pruebe esto en su lugar:
find / -size +100M -atime +30 \
-exec sh -c 'mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;
Para probar cosas, puedes reemplazar mv
con echo mv
, así:
find / -size +100M -atime +30 \
-exec sh -c 'echo mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;
...y vea cómo se ven los comandos generados.
Respuesta2
Mejoré un poco la solución de Lark para realizar una sola sh
llamada:
find / -size +100M -atime +30 -exec sh -c \
'for f do mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"; done' sh {} +
Alternativamente, sin ninguna sh
llamada:
while IFS= read -r f; do
mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"
done < <(find / -size +100M -atime +30)
(Esto último, bajo el supuesto de que los nombres de los archivos no tienen nuevas líneas).
Para la depuración, es posible que desee agregar -v
( mv
si es compatible).