Como mover os arquivos com base no ano

14

Preciso mover arquivos com base em um ano. Eu usei o findcomando

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

mas para que este comando seja executado com sucesso, preciso saber exatamente mtimeagora 470 é apenas um palpite. Significa que se eu puder dar o ano de 2012, ele me fornecerá arquivos relacionados apenas a 2012.

Então, eu preciso de conselhos sobre como

Encontre arquivos com base no ano, por exemplo, 2012 e mova-os para outro diretório.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 
OmiPenguin
fonte
Faz sentido usar em -exec ls ... \;vez de -exec ... +? O seu achado é velho demais para isso? Nesse caso, find ... -print0 | xargs -0 ls...seria muito mais rápido.
Hauke Laging
Desejo que essas perguntas (e respostas) que lidam com coreutils especifiquem rotineiramente se estamos lidando com utilitários GNU ou BSD (ou outros).
labirinto

Respostas:

37

Você deseja usar a -newermtopção para find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

para obter todos os arquivos com hora de modificação em 2012.

Se sua descoberta não suportar, -newermtvocê também pode fazer o seguinte para impedir o uso de cálculos de deslocamento:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref
Anthon
fonte
1
bandeira -newermt não está disponível no comando Localizar
OmiPenguin
Essa deve ser uma versão antiga do achado do seu RHEL? I irá fornecer uma alternativa no resposta para isso
Anthon
Sim este é 5.2
OmiPenguin
Suponho que é a revisão do RHEL, não da find(eu tenho encontrar a versão 4.4.2)
Anthon
1
A opção newermt não apareceu no find até as versões posteriores à v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
Slm
5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls não faz nenhum sentido.

Hauke ​​Laging
fonte
1
-exec ls -lfaz mais sentido e ainda mais durante o teste.
precisa saber é o seguinte
@ MichaelKjörling findpode imprimir tudo o que lspode. OK, com uma exceção: escapar / citar caracteres desagradáveis. Mas, em geral, a saída de findpode ser classificada diretamente. Chamadas inúteis de ls não tornam a coisa toda mais rápida.
Hauke Laging
Costumo usar algo bastante semelhante (embora pessoalmente prefira -printou possivelmente -ls ) durante os testes. A vantagem de usar -exec ls {}é que ele já executa algo externo para encontrar . Assim, quando você muda de lspara mv, as alterações reais são mínimas.
um CVn
3

De acordo com a página do manual, o argumento para -mtime é o número de dias que você está procurando. Você pode usar date +%jpara encontrar o número de dias desde 1º de janeiro do ano atual.

Bratchley
fonte
2
Bom caminho. Ser muito "nitpicky": -mtime -1: é qualquer arquivo nas últimas 24 horas. Não apenas os arquivos de ontem (ou hoje). Portanto, também haverá uma pequena "sobreposição": se você determinar que já faz 120 dias desde 2012 e hoje são 15:45 quando você inicia o script, acaba selecionando arquivos até 31 de dezembro 15:45 ( e não os últimos desse dia) ... Você provavelmente pode usar: nb_day - 1 e depois "eliminar" os poucos que datam de 2013 (esses podem ser encontrados por um ls -l | grep -v, MAS a saída diferente se eles são 1 dia apenas ... lotes de armadilhas ...)
Olivier Dulac
Você deseja usar a -daystartopção se deseja trabalhar -mtime. Caso contrário, você terá problemas com os arquivos no início e no final do ano, seja qual for a sua forma, a menos que você execute exatamente à meia-noite. Você pode fazer o deslocamento com mais precisão do -mminque com -mtimese puder encontrar facilmente o número de minutos desde o ano novo. Mas o mesmo problema existe com isso -mtime, apenas com menos arquivos (aqueles em um minuto por volta da meia-noite de ano novo).
Anthon
1
Sim, relendo a página de manual. Estou vendo como se divide em horas, portanto, fazer um simples find -mtime $("date -+%j")provavelmente não dará ao OP o que ele está fazendo. Estou deixando para a posteridade, já que isso parece um possível ponto cego para as pessoas caírem.
Bratchley
2

Você pode tentar usar uma combinação com os comandos state / ou datecomo nas seguintes linhas:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Nos dois casos, a abordagem é usar o datecomando para extrair o ano da última hora de modificação de cada arquivo e, em seguida, construir um caminho com este ano. O comando mkdir -pcriará esse caminho se ele ainda não existir. Claro que você pode usar outras findopções para refinar sua pesquisa.

woodengod
fonte
1

Se você fizer isso no diretório de trabalho, poderá fazer isso:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Isso simplifica consideravelmente as coisas e não causa sobreposição. Mas também pressupõe que esses arquivos tenham mais de 6 meses e que lsimprimam o ano em vez da hora exata.

Para arquivos com mais de 6 meses, basta substituí-lo por:

ls -l |awk '{ if ($6 == "May") print $9 }' 

ou algo semelhante, dependendo do mês. Se você deseja criar uma lista de meses para a qual mover arquivos (ou se deseja criar uma lista por anos), faça o seguinte:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
Ernie
fonte