Назад | Перейти на главную страницу

Переместить 53 800+ файлов в 54 отдельные папки по ~ 1000 файлов в каждой?

Попытка импортировать более 53 800 отдельных файлов (сообщений) с помощью сборщика POP Gmail.

Gmail по понятным причинам отказывается, выдавая ошибку: «Слишком много сообщений для загрузки. Слишком много сообщений на другом сервере».

Рассматриваемая папка выглядит примерно так:

/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
...

Используя оболочку (tcsh, sh и т. Д. Во FreeBSD), какую однострочную команду я могу ввести, чтобы разделить этот каталог, полный файлов, на отдельные папки, чтобы Gmail видел только 1000 сообщений за раз? Что-то с find или ls | xargs mv может быть. Что бы ни было быстрее.

Желаемый выходной каталог теперь будет выглядеть примерно так:

/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.)

Это не однострочник, но вы можете копировать такие фрагменты (в csh):

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

Я не уверен на 100%, что pipe будет работать с тем количеством файлов, которое у вас есть, но попробовать стоит. Кроме того, с помощью этой команды вы можете выполнять 500 за раз, просто измените это значение с 1000 на 500.

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

свернуто в одну строку (и с удаленной защитой 'echo'):

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

Это не самый быстрый, но чистый. это решение позволяет избежать синтаксического анализа вывода ls http://mywiki.wooledge.org/ParsingLs и цитирует ссылки на «$ file», иначе файлы с ненормальными именами (как это часто бывает в файлах Maildir) нарушат код. Например, если в каком-либо из файлов есть пробелы или точки с запятой, то ссылка на $ file без кавычек не приведет вас далеко (в большинстве случаев)

Подробнее о цитировании: http://mywiki.wooledge.org/Quotes и http://wiki.bash-hackers.org/syntax/words