Usando mv para mover para outro diretório e renomear de uma só vez

Usando mv para mover para outro diretório e renomear de uma só vez

Gostaria de saber todos os arquivos que têm +100Mb e não foram acessados ​​no último mês, e escrevi com sucesso:

find / -size +100M -atime +30

E agora quero mover esses arquivos para uma pasta chamada /big-not-used alterando seu nome como: file_nameYYYYMMDDonde file_name é o nome do arquivo original e YYYYMMDD é a data de hoje, no ano mês dia. Por exemplo film.mkvvai para/big-not-used/film.mkv20161031

Minha frase seria:

find / -size +100M -atime +30 -exec mv {} /big-not-used/... \;

Mas não sei como acrescentar a data de hoje ao nome do arquivo. Eu descobri que date +%Y-%m-%dresulta: 2016-10-31o que é útil. Agora a dúvida é como conseguir o nome desse arquivo? Seguindo: https://stackoverflow.com/questions/5456120/how-to-only-get-file-name-with-linux-find

... -exec basename {} \;

Talvez?:

find / -size +100M -atime +30 -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

Mas dá um erro porque basename está respondendo com o caminho completo do arquivo em vez do nome que eu usaria:

${var##/*/}

para obter o nome do arquivo, mas a questão é como inserir quais basename {}respostas no var na expressão anterior!?.

Talvez?

$(${$(basename {})##/*/})

Mas diz erro sintático próximo ao inesperado '}'...

Responder1

Você estava chegando perto de:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/$(basename {})$(date +%Y-%m-%d) \;

Mas sem citar, a expansão do shell das $(...)construções aconteceantes do findcomando ser executado. Em outras palavras, dada a linha de comando acima, o que realmente é executado é:

find / -size +100M -atime +30 \
  -exec mv {} /big-not-used/{}2016-10-30 \;

Porque o resultado de $(basename {})é justo {}e é por isso que você obtém o nome do caminho completo. Em vez disso, tente isto:

find / -size +100M -atime +30 \
  -exec sh -c 'mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

Para testar as coisas, você pode substituir mvpor echo mv, assim:

find / -size +100M -atime +30 \
  -exec sh -c 'echo mv {} /tmp/big-not-used/$(basename {})$(date +%Y-%m-%d)' \;

...e veja como são os comandos gerados.

Responder2

Melhorei um pouco a solução do Lark para fazer apenas uma shchamada:

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, sem nenhuma shchamada:

while IFS= read -r f; do
  mv "$f" /tmp/big-not-used/"$(basename "$f")$(date +%Y-%m-%d)"
done < <(find / -size +100M -atime +30)

(Último, sob a suposição de que os nomes dos arquivos não contêm novas linhas.)

Para depuração, você pode querer adicionar -v( mvse for compatível).

informação relacionada