Move 53.800+ arquivos para 54 pastas separadas com ~ 1000 arquivos cada?

2

Tentando importar mais de 53.800 arquivos individuais (mensagens) usando o buscador POP do Gmail.

O Gmail recusa-se compreensivelmente, apresentando o erro: "Muitas mensagens para descarregar. Existem demasiadas mensagens no outro servidor."

A pasta em questão parece semelhante a:

/usr/home/customer/Maildir/cur/1203672790.V57I586f04M867101.mail.net:2,S
/usr/home/customer/Maildir/cur/1203676329.V57I586f22M520117.mail.net:2,S
/usr/home/customer/Maildir/cur/1203677194.V57I586f26M688004.mail.net:2,S
/usr/home/customer/Maildir/cur/1203679158.V57I586f2bM182864.mail.net:2,S
/usr/home/customer/Maildir/cur/1203680493.V57I586f33M740378.mail.net:2,S
/usr/home/customer/Maildir/cur/1203685837.V57I586f0bM835200.mail.net:2,S
/usr/home/customer/Maildir/cur/1203687920.V57I586f65M995884.mail.net:2,S
...

Usando o shell (tcsh, sh, etc. no FreeBSD), que comando de uma linha posso digitar para dividir este diretório cheio de arquivos em pastas separadas para que o Gmail veja apenas 1000 mensagens de cada vez? Algo com find ou ls | xargs mv talvez. O que quer que seja mais rápido.

O diretório de saída desejado agora seria parecido com:

/usr/home/customer/Maildir/cur/1203672790.V57I586f04M867101.mail.net:2,S
/usr/home/customer/Maildir/cur/1203676329.V57I586f22M520117.mail.net:2,S
...
/usr/home/customer/set1/ (contains messages 1-1000)
/usr/home/customer/set2/ (contains messages 1001-2000)
/usr/home/customer/set3/ (etc.)
    
por ane 11.03.2010 / 19:39

2 respostas

4

Não é um one-liner, mas você pode copiar trechos como este (em csh):

foreach file ('ls | head -n 1000')
mv $file /tmp/new/dir
end

Não tenho 100% de certeza de que o pipe funcionará com o número de arquivos que você tem, mas vale a pena um tiro. Além disso, você pode fazer 500 de cada vez com este comando, apenas mude de 1000 para 500.

    
por 11.03.2010 / 20:15
1
count=target=0;

find srcdir/ -type f |
    while read file; do

        count=$((count+1));
        target=$((count/10000));

        [ -d $target ] || mkdir $target

        echo mv "$file" $target; #remove the 'echo' if you like what you see
    done

reduzida a uma única linha (e com a salvaguarda 'echo' removida):

count=target=0; find srcdir/ -type f | while read file; do count=$((count+1)); target=$((count/10000)); [ -d $target ] || mkdir $target; mv "$file" $target; done

Este não é o mais rápido, mas está limpo. esta solução evita analisar a saída do link 'ls' e cita as referências a "$ file", caso contrário arquivos com nomes anormais (como Maildir arquivos são frequentemente) iria quebrar o código. Por exemplo, se algum dos arquivos tiver espaços ou ponto-e-vírgulas, referenciar o arquivo $ sem aspas não o levará longe (na maior parte do tempo)

Leia mais sobre as citações: link e link

    
por 16.06.2010 / 10:11