Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Разделение текстового файла на переменное количество частей и перемещение этих частей

Ответить
Настройки темы
CMD/BAT - Разделение текстового файла на переменное количество частей и перемещение этих частей

Новый участник


Сообщения: 40
Благодарности: 0

Профиль | Отправить PM | Цитировать


С Вашей помощью у меня получается создать папки с плейлистами
Срипт
Код: Выделить весь код
@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"

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

Отправлено: 21:43, 27-02-2016

 

Новый участник


Сообщения: 40
Благодарности: 0

Профиль | Отправить PM | Цитировать


Упрощу задачу.
Есть структура директорий\файлов
Цитата:
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" удаляется.

Отправлено: 16:40, 28-02-2016 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Новый участник


Сообщения: 40
Благодарности: 0

Профиль | Отправить PM | Цитировать


Вот что я сварганил на эту тему в смысле условий
Код: Выделить весь код
@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!"
Но дальше я в ступоре. Те решения, которые я нашел в сети, относятся к разделению на заданное в условии количество строк. А вот как разделить на заданное количество равных частей - не нашел.

Последний раз редактировалось krokradio, 28-02-2016 в 18:08.


Отправлено: 18:01, 28-02-2016 | #3


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


Из вашего объяснения мало чего понятно, я понял только, что надо разделить файл на равное кол-во строк. Пример, как можно разделить файл на равные части:
Код: Выделить весь код
@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

Отправлено: 20:51, 28-02-2016 | #4


Новый участник


Сообщения: 40
Благодарности: 0

Профиль | Отправить PM | Цитировать


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

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

Отправлено: 22:56, 28-02-2016 | #5


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата krokradio:
будет ли ваш пример PowerShell работать в Win XP SP3? »
Будет. Надо только его установить: Windows Management Framework (Windows PowerShell 2.0, WinRM 2.0 и BITS 4.0).

Цитата krokradio:
Возможно мне стоит описать полностью все задание и выложить на фрилансе? »
Стоит. Не только на фрилансе, но и здесь.
Это сообщение посчитали полезным следующие участники:

Отправлено: 00:12, 29-02-2016 | #6


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


Цитата 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
Это сообщение посчитали полезным следующие участники:

Отправлено: 00:17, 29-02-2016 | #7


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


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

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

Отправлено: 01:12, 29-02-2016 | #8


Новый участник


Сообщения: 40
Благодарности: 0

Профиль | Отправить PM | Цитировать


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 частей. »
Абсолютно верно

Отправлено: 01:16, 29-02-2016 | #9


Ветеран


Сообщения: 1754
Благодарности: 965

Профиль | Цитировать


Цитата 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% кол-во частей
Это сообщение посчитали полезным следующие участники:

Отправлено: 02:17, 29-02-2016 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Разделение текстового файла на переменное количество частей и перемещение этих частей

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - Разделение текстового файла на части без разделения абзацев Re:Flex Скриптовые языки администрирования Windows 9 09-07-2013 04:35
Разделения экрана на несколько частей ViRTaCe Хочу все знать 5 22-03-2013 01:11
Как разбить *.avi файл на 2 и более частей azbest Видео и аудио: обработка и кодирование 10 20-10-2009 15:58
Download Master (архив разбит на несколько частей) Kindmankind Хочу все знать 11 19-03-2009 23:55
Как разбить большой кусок текста на несколько частей chem1 Вебмастеру 11 25-05-2008 16:32




 
Переход