Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Разделение текстового файла на переменное количество частей и перемещение этих частей (http://forum.oszone.net/showthread.php?t=312102)

krokradio 27-02-2016 21:43 2610968

Разделение текстового файла на переменное количество частей и перемещение этих частей
 
С Вашей помощью у меня получается создать папки с плейлистами
Срипт
Код:

@echo off
setlocal enabledelayedexpansion
>nul chcp 1251

set "src=F:\Music\Test"
set "dest=F:\Music\MPL"
set "files=*.mp3"
set "playlistext=.alb"
 
2>nul (md "%dest%"
for /f "delims=" %%i in ('dir/ad/b "%src%"') do >"%dest%\%%i%playlistext%" dir/a-d/b/s "%src%\%%i\%files%")
For %%a in (F:\Music\MPL\*.alb) do md "F:\Music\MPL\%%~na"& move "%%~a" "F:\Music\MPL\%%~na"

for /f "tokens=*" %%i in ('dir /b /s F:\Music\MPL\*.alb') do (

    for /f "tokens=*" %%j in ('type "%%i"') do call:set_random "%%j"
    call:set_content "%%i"

)

goto:eof

:set_random
set "line_%random%=%~1"
goto:eof

:set_content

1>%1 (

for /f "tokens=2* delims==" %%i in ('set line_') do echo %%i

)

for /f "tokens=1 delims==" %%i in ('set line_') do set "%%i="



В папке "E:\Air\playlists" у меня лежит много подпапок. В каждой подпапке есть папка "elements"
elements
Цитата:

E:\Air\playlists\Folder01\elements
E:\Air\playlists\Folder02\elements
E:\Air\playlists\Folder03\elements
E:\Air\playlists\*\elements


В папках "elements" лежат миниплейлисты. Их имена = именам плейлистов, которые созданы предыдущим скриптом, но с тегами 01, 02, 03...
Пример:
1. В папке "F:\Music\MPL\Chillout" есть файл "chillout.alb". В папке "E:\Air\playlists\Folder01\elements" есть файл "chillout01.alb", а в папке "E:\Air\playlists\Folder03\elements" есть файл "chillout02.alb". В остальных папках "E:\Air\playlists\*\elements" файлы "chillout**.alb" отсутствуют. Всего 2.
В папке "F:\Music\MPL\Trance" есть файл "trance.alb". В папке "E:\Air\playlists\Folder01\elements" есть файл "trance01.alb", в папке "E:\Air\playlists\Folder02\elements" есть файл "trance02.alb", а в папке "E:\Air\playlists\Folder04\elements" есть файл "trance03.alb". В остальных папках "E:\Air\playlists\*\elements" файлы "trance**.alb" отсутствуют. Всего 3.
2. После запуска скрипта он должен определить, что в подпапках "F:\Music\MPL" есть файл "chillout.alb", а во всех подпапках "E:\Air\playlists\*\elements" есть 2 файла с тегом "chillout" в названии. То же самое сравнение для "trance" и всех остальных.
3. Скипт разделяет файл "F:\Music\MPL\Chillout\chillout.alb" на "F:\Music\MPL\Chillout\chillout01.alb" и "F:\Music\MPL\Chillout\chillout02.alb" с одинаковым количеством строк. "F:\Music\MPL\Trance\trance.alb" разделяет на "F:\Music\MPL\Trance\trance01.alb", "F:\Music\MPL\Trance\trance02.alb" и "F:\Music\MPL\Trance\trance03.alb" с одинаковым количеством строк.
4. Замена существующих "E:\Air\playlists\*\elements\chillout**.alb" и "E:\Air\playlists\*\elements\trance**.alb" новыми "F:\Music\MPL\Chillout\chillout**.alb" и "F:\Music\MPL\Trance\trance**.alb"

Вот как-то так. Надеюсь я не путано объяснил, что я хочу получить в итоге?

krokradio 28-02-2016 16:40 2611135

Упрощу задачу.
Есть структура директорий\файлов
Цитата:

F:\Music\MPL\Chillout(2)\chillout(2).alb
F:\Music\MPL\Trance(4)\Trance(4).alb
F:\Music\MPL\Rock(6)\Trance(6).alb
F:\Music\MPL\*(**)\*(**).alb
У нас получается 3 переменных:
Код:

Set "dir=F:\Music\MPL\*"
Set "name=F:\Music\MPL\*\*(**).alb"
Set "n=(**)

Я понимаю, что условия я изначально задаю не правильно и скорее всего оно должно иметь вид типа:
Код:

for /f "tokens=*" %%i in (ля-ля-ля) do (
 лю-лю-лю

и т.д., но для меня программирование - темный лес. Могу экспериментировать только методом логической подстановки.

Скрипт должен смотреть на теги (**) файлов "*(**).alb" и разделять этот файл на (**) файлов с равным количеством строк, создавая например из файла "chillout(2).alb" два файла "chillout 01.alb" и "chillout 02.alb", после чего исходный файл "chillout(2).alb" удаляется.

krokradio 28-02-2016 18:01 2611153

Вот что я сварганил на эту тему в смысле условий
Код:

@Echo On
SetLocal enabledelayedexpansion

:: Имена файлов:
:: F:\Music\MPL\Chillout_02\chillout_2.alb
:: F:\Music\MPL\Trance_04\Trance_4.alb
:: F:\Music\MPL\Rock_06\Rock_6.alb

For /F "tokens=* usebackq delims=_" %%i In ('dir /b /s F:\Music\MPL\*.alb') Do (

    for /f "tokens=*" %%j in ('type "%%i"') do call:set_divided "%%j"
       
)

goto:eof

:set_divided

Set "Fullname=%%i"
Set "Filename=!Fullname:-6!"
Set "Tag=!Fullname:~Filename,-4!"

Но дальше я в ступоре. Те решения, которые я нашел в сети, относятся к разделению на заданное в условии количество строк. А вот как разделить на заданное количество равных частей - не нашел.

Foreigner 28-02-2016 20:51 2611206

Из вашего объяснения мало чего понятно, я понял только, что надо разделить файл на равное кол-во строк. Пример, как можно разделить файл на равные части:
Код:

@echo off
setlocal

set cnt=100
set step=4

for /f "tokens=*" %%i in ('type test.txt') do call:0 "%%i"
for /l %%i in (101,%step%,%cnt%) do call:1 %%i
goto:eof

:0
set /a cnt+=1
set "line_%cnt%=%~1"
goto:eof

:1
set /a part+=1
set /a n=%1+step-1

1>test_%part%.txt (

for /l %%i in (%1,1,%n%) do if defined line_%%i (

        for /f "tokens=2 delims==" %%j in ('set line_%%i') do echo %%j

))

В переменной step задается кол-во строк в каждом файле.
В последнем файле будет остаток.

ЗЫ. батники, это худший из вариантов для работы с текстом.
ЗЫЫ. Если вам надо просто составить плейлисты для эфира, то проще взять некоторое кол-во файлов из ВСЕЙ коллекции, в произвольном порядке и не мучиться с составлением каких-то промежуточных плейлистов. Например, нужно воспроизвести 10 произвольных файлов из 100 Гб музыки. Как я это решил для себя на PowerShell:
Код:

param ($count = 10, $root = 'D:\MUSIC')
$plist = (get-childitem $root *.mp3 -recurse | get-random -count $count).fullname
$plist

Результат вывода переменной $plist (ее можно сразу перенаправить в проигрыватель (зависит от проигрывателя) или сохранить в файл):
Код:

D:\MUSIC\NATIVE\Руян\2014. Лебедь Белая\06 - Дружина.mp3
D:\MUSIC\FOREIGN\The Sullen Route\2011. Apocalyclinic\06 - Tonight's Avenue.mp3
D:\MUSIC\FOREIGN\Rosetta\2015. Rosetta - Audio-Visual Original Score\04 - Tape A.mp3
D:\MUSIC\FOREIGN\Poets Of The Fall\2012. Temple Of Thought\03 - Cradled in Love.mp3
D:\MUSIC\FOREIGN\Heaven Shall Burn\2013. Veto\CD-1. Veto\11 - Beyond Redemption.mp3
D:\MUSIC\FOREIGN\Neurotech\2011. Antagonist\02 - Inject Me Now.mp3
D:\MUSIC\FOREIGN\Devin Townsend\The Devin Townsend Band\2006. Synchestra (Special Edition)\05 - Vampolka.mp3
D:\MUSIC\FOREIGN\Boards of Canada\2013. Tomorrow's Harvest\15 - New Seeds.mp3
D:\MUSIC\FOREIGN\Ill Niño\2012. Epidemia\10 - Invisible People.mp3
D:\MUSIC\FOREIGN\Riding Along For Thousands Of Miles\2011. Brick City Gost\07 - Final Notice.mp3


krokradio 28-02-2016 22:56 2611228

Foreigner, примеров разделения по количеству строк много. Мне же нужно разделение на части.
Например есть 3 файла. В одном 2000 строк и его надо разделить на 4 равных части. то есть должно получиться 4 файла по 500 строк. В другом 1500 строк и его надо разделить на 2 части по 750 строк, в третьем 1500 строк и его надо разделить на 3 части по 500 строк.

Учитывая, что я в языках полный ноль, подскажите, будет ли ваш пример PowerShell работать в Win XP SP3? Возможно мне стоит описать полностью все задание и выложить на фрилансе? Но какой язык мне просить на реализацию задания? К сожалению я жестко привязан к Win XP SP3. Эфир полностью автоматизирован на QBasic.

Iska 29-02-2016 00:12 2611246

Цитата:

Цитата krokradio
будет ли ваш пример PowerShell работать в Win XP SP3? »

Будет. Надо только его установить: Windows Management Framework (Windows PowerShell 2.0, WinRM 2.0 и BITS 4.0).

Цитата:

Цитата krokradio
Возможно мне стоит описать полностью все задание и выложить на фрилансе? »

Стоит. Не только на фрилансе, но и здесь.

Foreigner 29-02-2016 00:17 2611249

Цитата:

Цитата krokradio
Мне же нужно разделение на части. »

Ну и? Я ровно про это. Батник разделяет файл на части по количеству строк. Ведь равные части бывают разные, можно файл из 2000 строк и на 2000 частей разбить.

Попробовал файл из 1500 строк разбить на три файла по 500. Все отработало корректно. Файл создал в PowerShell (так проще):
Код:

& {for ($i = 1; $i -le 1500; $i++) { "$('{0:d4}. ' -f $i)$(get-random)" }} | sc test.txt
Он имеет вид:
Код:

0001. 1684051906
0002. 150225868
0003. 538389330
0004. 541472203
...
1500. 233788911

Батник слегка изменил под большее число строк:
Код:

@echo off
setlocal

set cnt=10000
set step=500

for /f "tokens=*" %%i in ('type test.txt') do call:0 "%%i"
for /l %%i in (10001,%step%,%cnt%) do call:1 %%i
goto:eof

:0
....

В результате появилось три файла по 500 строк (0001...0500; 0501...1000; 1001...1500)

Проблема батника при работе с текстом -- есть большая вероятность, что при попадании в раздачу спец.символов (=,&,|,%,>,<) результат может оказаться не тем, который вы ожидаете увидеть. Все это так или иначе решается, но если честно нет особого желания этого делать.

Ну а PowerShell на Win ХР надо ставить дополнительно (будет вторая версия) + Net.Framework. Код, с небольшими изменениями, будет работать:
Код:

param ($count = 10, $root = 'D:\MUSIC')
$plist = get-childitem $root *.mp3 -recurse | get-random -count $count | % { $_.fullname }
$plist


Iska 29-02-2016 01:12 2611254

Цитата:

Цитата Foreigner
Ну и? Я ровно про это. »

Не совсем. Нужно дополнительное действие, ибо, насколько я понимаю, он хочет делить не по X строк, а на Y частей, то есть — посчитать количество строк в файле и разделить на эти самые Y частей.

Цитата:

Цитата Foreigner
Проблема батника при работе с текстом -- есть большая вероятность, что при попадании в раздачу спец.символов (=,&,|,%,>,<) результат может оказаться не тем, который вы ожидаете увидеть. Все это так или иначе решается, но если честно нет особого желания этого делать. »

Всецело поддерживаю :)!

krokradio 29-02-2016 01:16 2611258

alb=txt
Весь скрипт должен отталкиваться от ini-файла в абзаце 5.

1. Есть коллекция музыки, распределенная в папках по стилям.
Цитата:

F:\Music\Chillout_2
F:\Music\Trance_4
F:\Music\Rock_5
F:\Music\*_*
2. Есть папки с плейлистами, из которой мой плеер берет информацию для эфира
Цитата:

E:\Air\playlists\one
E:\Air\playlists\two
E:\Air\playlists\three
E:\Air\playlists\four
E:\Air\playlists\*
3. В каждой папке "E:\Air\playlists\*" есть подпапка "elements" и файл MAIN.alb

В принципе уже есть скрипт "Windows Batch file", который создает из коллекции готовые плейлисты, но учитывая весь объем задания, скорее всего его придется переписывать под другой язык
Скрытый текст
Код:

@echo off
setlocal enabledelayedexpansion
>nul chcp 1251
 
set "src=F:\Music"
set "dest=F:\MPL"
set "files=*.mp3"
set "playlistext=.alb"
 
2>nul (md "%dest%"
for /f "delims=" %%i in ('dir/ad/b "%src%"') do >"%dest%\%%i%playlistext%" dir/a-d/b/s "%src%\%%i\%files%")
For %%a in (F:\MPL\*.alb) do md "F:\MPL\%%~na"& move "%%~a" "F:\MPL\%%~na"
 
for /f "tokens=*" %%i in ('dir /b /s F:\MPL\*.alb') do (
 
    for /f "tokens=*" %%j in ('type "%%i"') do call:set_random "%%j"
    call:set_content "%%i"
 
)
 
goto:eof
 
:set_random
set "line_%random%=%~1"
goto:eof
 
:set_content
 
1>%1 (
 
for /f "tokens=2* delims==" %%i in ('set line_') do echo %%i
 
)
 
for /f "tokens=1 delims==" %%i in ('set line_') do set "%%i="



Этот скрипт опираясь на структуру папок в "F:\Music" создает в папке "F:\MPL" такую же структуру директорий и в каждую подпапку кладет плейлист с таким же именем, как и у подпапки.
На выходе получается

Цитата:

F:\MPL\Chillout_2\chillout_2.alb
F:\MPL\Trance_4\Trance_4.alb
F:\MPL\Rock_5\Rock_5.alb
F:\MPL\*_*\*_*.alb
ВАЖНО!!! Как видно из кода, эти плейлисты создаются уже перемешанными, то есть с функцией "random".

4. У каждого созданного плейлиста в имени есть цифровой тег "_*". Этот тег задает количество миниплейлистов, на которое должен быть разбит плейлист. То есть, если у нас есть "F:\MPL\Chillout_2\chillout_2.alb" на "х" строк, то из него должно получится "F:\MPL\Chillout_2\chillout 01.alb" на "Х/2" строк и "F:\MPL\Chillout_2\chillout 02.alb" на "х/2" строк а сам "F:\MPL\Chillout_2\chillout_2.alb" должен быть удален.
Если в теге файла кроме основного есть еще значение "с" (на пример "F:\MPL\Jazz_c_10\Jazz_c_10.alb"), то файл не разбивается на строки, а из него просто делается 10 копий с именами
Цитата:

F:\MPL\Jazz_c_10\Jazz 01.alb
F:\MPL\Jazz_c_10\Jazz 02.alb
F:\MPL\Jazz_c_10\Jazz 03.alb
.......
F:\MPL\Jazz_c_10\Jazz 10.alb
а сам "F:\MPL\Jazz_c_10\Jazz_c_10.alb" должен быть удален.

5. Перемещение. Я создам "F:\MPL\plst.ini" в котором задам соответствие такого типа
Цитата:

Music = F:\Music
Playlists = F:\MPL
E:\Air\playlists\one\elements = Chillout, New Age
E:\Air\playlists\two\elements = Chillout, Trance, New Age
E:\Air\playlists\three\elements = Trance, Jazz
E:\Air\playlists\four\elements = Jazz, Rock
и т.д.
Вот тут как бы правильно объяснить....
Для начала все папки "E:\Air\playlists\*\elements" должны очищаться.
В примерах выше я разбивал "F:\MPL\Chillout_2\chillout_2.alb" на "F:\MPL\Chillout_2\chillout 01.alb" и "F:\MPL\Chillout_2\chillout 02.alb".
В "F:\MPL\plst.ini" у нас указано, что "F:\MPL\Chillout_2\chillout 01.alb" и "F:\MPL\Chillout_2\chillout 02.alb" должны попадать в "E:\Air\playlists\one\elements" и "E:\Air\playlists\two\elements".
То есть "chillout 01.alb" перемещается в "E:\Air\playlists\one\elements", "chillout 02.alb" в "E:\Air\playlists\two\elements". И так для остальных...

6. После такого распределения у нас в папках "E:\Air\playlists\*\elements" оказывается много миниплейлистов. На пример в папке "E:\Air\playlists\two\elements" появляется три миниплейлиста ("Chillout 02.alb", "Trance 01.alb" и "New Age 02.alb").
Выше я писал, что в каждой папке "E:\Air\playlists\*" есть файл "MAIN.alb". Нам нужно файлы "Chillout 02.alb", "Trance 01.alb" и "New Age 02.alb" соединить в один, перемешать/рандомизировать его и сохранить как "E:\Air\playlists\*\MAIN.alb" заменив им старый.

Вот как-то так. Предложения в личку.

Цитата:

Цитата Iska
Проблема батника при работе с текстом -- есть большая вероятность, что при попадании в раздачу спец.символов (=,&,|,%,>,<) результат может оказаться не тем, который вы ожидаете увидеть. Все это так или иначе решается, но если честно нет особого желания этого делать. »

Такого получится не может, так как я всю базу музыки предварительно прогоняю через TagScaner избавляясь не только от спецсимволов, но даже на всякий случай от букв "й" и "ё".

Цитата:

Цитата Iska
насколько я понимаю, он хочет делить не по X строк, а на Y частей, то есть — посчитать количество строк в файле и разделить на эти самые Y частей. »

Абсолютно верно

Foreigner 29-02-2016 02:17 2611266

Цитата:

Цитата krokradio
Абсолютно верно »

Это почти одно и тоже, просто делим кол-во строк на кол-во частей:
Код:

@echo off
setlocal

set cnt=10000
set p=4

for /f "tokens=*" %%i in ('type test.txt') do call:0 "%%i"
set /a step=(cnt-10000)/p
.....

Где переменная %p% кол-во частей

krokradio 29-02-2016 13:16 2611377

Всем спасибо. Принято в работу фрилансером.


Время: 16:35.

Время: 16:35.
© OSzone.net 2001-