Usar mv para pasar a otro directorio y cambiar el nombre de inmediato

Usar mv para pasar a otro directorio y cambiar el nombre de inmediato

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_nameYYYYMMDDdonde nombre_archivo es el nombre del archivo original y AAAAMMDD es la fecha de hoy, en año mes día. Por ejemplo film.mkvva 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-%dlos resultados son: 2016-10-31lo 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 findcomando. 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 mvcon 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 shllamada:

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 shllamada:

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( mvsi es compatible).

información relacionada