Показать полную графическую версию : удаление файлов по списку list.txt
всем привет.
есть скрипт, в конце скрипта прописано удаление файлов которые указаны в списке list.txt
скрипт пашет, но выдает кучу ошибок в конце
в данный момент он выглядит так
@echo off
setlocal
1>nul chcp 1251
cd C:\vs
(for %%i in (*.jpg) do @echo file '%%i') > list.txt
ffmpeg -f concat -safe 0 -r 2 -i list.txt -threads 2 -vcodec libx264 -preset veryfast -qp 30 -tune grain -r 1 -framerate 1 30.avi
call
For /F "delims=" %%A In ('Dir "*.*" /A-D /B') Do (Echo %%~A)>>list.txt
For /f "tokens=*" %%i in (list.txt) do attrib -a %%i
attrib -a %0
del /aa /q /f *.*
del list.txt
pause
после отрабатывания скрипта, он все за собой чистит но в cmd ошибки
ошибка в формате параметра
и ошибок этих столько, сколько файлов я обрабатываю. а их несколько тысяч. в итоге скрипт отрабатывает за 1 минуту грубо говоря и 5 минут срет в лог ошибку формата параметра.
чоделатьпомогите
Потому что у Вас какая-то сборная солянка в коде.
отсюда
@echo off
setlocal
1>nul chcp 1251
cd C:\vs
(for %%i in (*.jpg) do @echo file '%%i') > list.txt
ffmpeg -f concat -safe 0 -r 2 -i list.txt -threads 2 -vcodec libx264 -preset veryfast -qp 30 -tune grain -r 1 -framerate 1 30.avi
до сюда оно перемещается по cd , создает текстовый файл и по беря из него названия файлов, склеивает их в видео
call следующая операция
отсюда
For /F "delims=" %%A In ('Dir "*.*" /A-D /B') Do (Echo %%~A)>>list.txt
For /f "tokens=*" %%i in (list.txt) do attrib -a %%i
attrib -a %0
del /aa /q /f *.*
del list.txt
pause
до сюда код спжен с просторов oszone написан для подчищения файлов после склеивания их в видосик.
bidjo,
может так?
for %%a in (*.jpg) do ffmpeg -f concat -safe 0 -r 2 -i %%a -threads 2 -vcodec libx264 -preset veryfast -qp 30 -tune grain -r 1 -framerate 1 30.avi
del *.jpg
pause
не не так. так просто я и сам умею:) надо что бы скрипт отрабатывал через планировщик раз в сутки и удалял только то что в файле. не более. пока он исполняется, могут появится новые файлы, которые не войдут в видео и будут удалены после исполнения скрипта.
bidjo, я вас огорчу, но
For /F "delims=" %%A In ('Dir "*.*" /A-D /B') Do (Echo %%~A)>>list.txt
For /f "tokens=*" %%i in (list.txt) do attrib -a %%i
attrib -a %0
del /aa /q /f *.*
del list.txt
идентично не то что
del *.jpg
а даже
del *.*
bidjo, так дело в том, что у Вас в файле list.txt не просто «файлы», а а) сначала идут записи вида:
file 'bla-bla-bla1.jpg'
file 'bla-bla-bla2.jpg'
…
file 'bla-bla-blaXXX.jpg'
и б) затем в нём же идут записи уже просто всех подряд файлов. Потому я и писал, что у Вас там сборная солянка в коде. Понятно, зачем собираются записи о *.jpg файлах в указанном выше виде — для последующей обработки их ffmpeg.exe. Но непонятно, зачем туда же потом дописываются записи обо всех подряд файлах. На кой шут для удаления задействуется архаичная и в целом порочная механика атрибуции (причём отдельной строкой — для самого пакетного файла :lol:). В предыдущем варианте (Любой язык - создание файла со списком файлов в папке (http://forum.oszone.net/thread-336055.html)) Вам требовалось собирать имена файлов пачками (дескать, ибо дюже много зараз), здесь же они собираются чохом — как понимать?
я вас огорчу, но »
и верно. не тестил на все файлы.
спасибо за подсказку.
так дело в том, что у Вас в файле list.txt не просто «файлы», а а) сначала идут записи вида:
и б) затем в нём же идут записи уже просто всех подряд файлов. Потому я и писал, что у Вас там сборная солянка в коде. Понятно, зачем собираются записи о *.jpg файлах в указанном выше виде — для последующей обработки их ffmpeg.exe. Но непонятно, зачем туда же потом дописываются записи обо всех подряд файлах. На кой шут для удаления задействуется архаичная и в целом порочная механика атрибуции (причём отдельной строкой — для самого пакетного файла ). В предыдущем варианте (Любой язык - создание файла со списком файлов в папке) Вам требовалось собирать имена файлов пачками (дескать, ибо дюже много зараз), здесь же они собираются чохом — как понимать? »
туда не записываются файлы все подряд, ток .jpg
в предыдущем варианте скрипт отрабатывает 960 файлов, в папке где их уже 50 и более тысяч. он для этого нужен. а скрипт concate нужен после, того как все устаканится и не будет такой чехарды.
For /F "delims=" %%A In ('Dir "*.*" /A-D /B') Do (Echo %%~A)>>list.txt
For /f "tokens=*" %%i in (list.txt) do attrib -a %%i
attrib -a %0
del /aa /q /f *.*
я честно спер с этого форума и он не работает как надо:) вот и прошу помощи
причём отдельной строкой — для самого пакетного файла [/post] это сделано специально, что бы скрипт подчищал за собой.
туда не записываются файлы все подряд, »
А это:
For /F "delims=" %%A In ('Dir "*.*" /A-D /B') Do (Echo %%~A)>>list.txt »
что тогда?
в предыдущем варианте скрипт отрабатывает 960 файлов, в папке где их уже 50 и более тысяч. он для этого нужен. а скрипт concate нужен после, того как все устаканится и не будет такой чехарды. »
А какая разница? Я лично не вижу никакой, что пятьдесят файлов обработать, что пятьдесят тысяч, что пятьдесят миллионов, алгоритм один и тот же.
Вот Вам код на PowerShell:
Param (
[System.String]$sSourceFolder = (Convert-Path -Path '.'),
[System.Int32]$iLimit = 100
)
if([System.IO.Directory]::Exists($sSourceFolder)) {
do {
$sFileList = [System.IO.Path]::Combine($sSourceFolder, [System.IO.Path]::GetRandomFileName())
} until(-not [System.IO.File]::Exists($sFileList))
$aFiles = Get-ChildItem -Path "$sSourceFolder\*.*" -File -Include '*.jpg', '*.jpeg', '*.jpe'
if($aFiles.Count -gt 0) {
$i = 0
foreach($oFile in $aFiles) {
Add-Member -InputObject $oFile -NotePropertyName Number -NotePropertyValue $i
$i++
}
$aFiles | Group-Object -Property { [Math]::Floor([System.Int32]$_.Number / $iLimit) } | ForEach-Object -Process {
$iListFileNumber = ([System.Int32]$_.Name) + 1
$iFilesCount = $_.Count
$_.Group | ForEach-Object -Begin {
$sContent = ''
} -Process {
$sContent += "file '$($_.Name)'`r`n"
} -End {
Out-File -InputObject $sContent -FilePath $sFileList -Encoding "Default" -NoNewline
Start-Process `
-FilePath 'C:\Program Files\FFmpeg\bin\ffmpeg.exe' `
-ArgumentList "-y -f concat -safe 0 -r 2 -i $([System.IO.Path]::GetFileName($sFileList)) -threads 2 -vcodec libx264 -preset veryfast -qp 30 -tune grain -r 1 -framerate 1 Output$($iListFileNumber.ToString("0000")).avi" `
-WorkingDirectory $sSourceFolder `
-NoNewWindow -Wait
Write-Host "$iFilesCount file(s) splitted into [Output$($iListFileNumber.ToString("0000")).avi]." -ForegroundColor Green
}
}
[System.IO.File]::Delete($sFileList)
switch($host.UI.PromptForChoice("Delete files?", "Delete all splitted jpeg files?", [System.Management.Automation.Host.ChoiceDescription[]] @("&Yes", "&No"), 1)) {
0 {
foreach($oFile in $aFiles) {
$oFile.Delete()
Write-Host "File [$($oFile.Name)] deleted."
}
Write-Host "Total $($aFiles.Count) file(s) deleted."
}
1 {
# Nothing to do
}
}
} else {
Write-Host "Can't find any jpeg files in source folder [$sSourceFolder], nothing to do." -ForegroundColor Green
}
} else {
Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
}
который использует два параметра — путь к целевому каталогу (по умолчанию — текущий каталог) и число файлов в «пачке» (по умолчанию — 100). В указанном каталоге ищутся все jpeg-файлы, группируются по заданному числу файлов в «пачке», для каждой группы имён создаётся файл, который указывается аргументом при вызове ffmpeg.exe, после отработки которого обрабатывается следующая группа файлов до их исчерпания. В конце задаётся вопрос, следует ли удалять обработанные jpeg-файлы (чтобы у Вас была возможность перед их удалением предварительно посмотреть на получившиеся avi-файлы и оценить результат).
Пример процесса обработки двадцати шести jpeg-файлов в текущем каталоге, по 10 файлов в пачке:
https://i.imgur.com/FhOLgu3.png
Итог обработки:
https://i.imgur.com/YiBBKVf.png
Вот Вам код на PowerShell »
зачем вы пишите такой лютый трэш и угар?
зачем вы пишите такой лютый трэш и угар? »
Поясните, пожалуйста, подробнее.
есть родные для PoSh типы данных string и int
проверку директории через [System.IO.Directory]::Exists допустим, понять можно - штатные способы "проглотят", например, путь к реестру
хотя в целом - это простой конвейер, если что-то не так с директорией, содержимым - сам командлет выдаст ошибку снабжённую всеми необходимыми атрибутами, на языке пользователя . "Плюнуть" на экран красный текст на иностранном языке - это для кого такое "удобство"? Оформляете в виде вызываемого скрипта, но он не формирует события ошибки.
Для создания временных файлов есть стандартные механизмы и места, для удаления файлов - тоже. Зачем вместо штатных команд использовать обращения к библиотекам .NET?
Синтетическое поле для каждого файла с номером - зачем?! - Они уже в пронумерованном массиве
Вместо округления результата деления и отдельный итератор для групп используют целочисленное деления и остаток от целочисленного деления.
Не надо явно указывать `r`n - это платформозависимое соглашение, а что PoSh, что ffmpeg работаею и на mac и на linux. Не надо в памяти формировать файлы - пишите сразу строки в файл
Пути к ffmpeg самое место в параметре по умолчанию, а не в середине скрипта
А вот результат работы ffmpeg как раз должен проверяться - сейчас если он не сможет создать видео (места на диске не хватило), скрипт всё равно бодро рапортует об успехе и удаляет исходные изображения. Наличие выходного файла тоже
Вместо велосипеда с PromptForChoice можно просто вызвать Remove-Item с параметром -Confirm. Вы так уверены, что выдавать на экран простыню из 960 имён удалённых файлов - хорошая идея? Если они важны - не лучше ли тогда использовать Write-Output - чтобы можно было их по необходимости передать по конвейеру и т.п.?
switch с единственным параметром тоже умиляет
Busla, спасибо, ясно.
есть родные для PoSh типы данных string и int »
Поясните подробнее, пожалуйста. Если Вы про [string] и [int] — в чём их «родность» для PowerShell и в чём отличие от [System.String] и [System.Int32]?
проверку директории через [System.IO.Directory]::Exists допустим, понять можно - штатные способы "проглотят", например, путь к реестру »
Я полагаю сие более правильным подходом, нежели использование командлета Test-Path. Просто, надёжно и удобно.
хотя в целом - это простой конвейер, если что-то не так с директорией, содержимым - сам командлет выдаст ошибку снабжённую всеми необходимыми атрибутами, на языке пользователя . »
Не могу с Вами согласиться, коллега:
https://i.imgur.com/eYejUiW.png
Красная портянка бывает и больше.
"Плюнуть" на экран красный текст на иностранном языке - это для кого такое "удобство"? »
Для себя. Это привычка.
Оформляете в виде вызываемого скрипта, но он не формирует события ошибки. »
Здесь Вы совершенно правы. Надо учиться, как это делать, и как это делать правильно.
Для создания временных файлов есть стандартные механизмы и места, »
Угу. Я использовал. Но у ffmpeg.exe есть свои принципы работы с путями, кодировками и конвеером :). Потому потребовалось выбирать — либо шашечки, либо ехать.
Зачем вместо штатных команд использовать обращения к библиотекам .NET? »
Как и в вышеупомянутом случае — потому что это проще, надёжнее и удобнее.
Синтетическое поле для каждого файла с номером - зачем?! - Они уже в пронумерованном массиве »
Потому что у меня возникла проблема — как вменяемо получить индекс элемента из массива объектов, полученного по Get-ChildItem. Можете показать, как сие сделать?
Вместо округления результата деления и отдельный итератор для групп используют целочисленное деления и остаток от целочисленного деления. »
Поясните, пожалуйста, подробнее.
Не надо явно указывать `r`n - это платформозависимое соглашение, а что PoSh, что ffmpeg работаею и на mac и на linux. »
Я не планирую работу скрипта под иные платформы.
Не надо в памяти формировать файлы - пишите сразу строки в файл »
Изначально я так и делал. Потом поменял логику работы. Что будет быстрее на большом количестве файлов — не проверял.
Пути к ffmpeg самое место в параметре по умолчанию, а не в середине скрипта »
Соглашусь полностью.
А вот результат работы ffmpeg как раз должен проверяться - сейчас если он не сможет создать видео (места на диске не хватило), скрипт всё равно бодро рапортует об успехе и удаляет исходные изображения. »
Соглашусь с оговоркой: всё равно надо смотреть полученный результат «глазками», и решение принимать по факту.
Наличие выходного файла тоже »
Видимо, мысль не закончена.
Вместо велосипеда с PromptForChoice можно просто вызвать Remove-Item с параметром -Confirm. »
Можно. Для отладки такие вещи: https://i.imgur.com/WANk1qY.pngгодятся. Для работы — навряд ли: неподготовленного пользователя такие вопросы вводят в ступор.
Вы так уверены, что выдавать на экран простыню из 960 имён удалённых файлов - хорошая идея? »
Нет. Не уверен.
Если они важны - не лучше ли тогда использовать Write-Output - чтобы можно было их по необходимости передать по конвейеру и т.п.? »
Угу.
switch с единственным параметром тоже умиляет »
Привычка. Во-первых, понятно, что это выбор из вариантов. Во-вторых, сегодняшний switch с двумя ветвями завтра может потребовать трёх и более вариантов выбора, и проще добавить ветви в уже существующую структуру, нежели переписывать if на switch.
как вменяемо получить индекс элемента из массива объектов, полученного по Get-ChildItem. »
Увы, вменяемо - вряд ли, нет встроенных инструментов. Но можно так:
function findex ($arr, $val) {
for ($i=0;$i -lt $arr.count;$i++) {
if($arr[$i] -eq $val){$i}
}
}
но лучше ведь так, имхо:
[array]::indexof($arr.name,'name.ext')
хотя, сейчас дошли руки проверить и это:
$arr.name.indexof('name.ext')
работает...
YuS_2, боюсь, с группировкой отобранных файлов мне это не особо поможет.
Iska,
Да, в код не вчитывался, комментировал только то, что процитировано...
В общем, суть задачи пока не разбирал, ничего добавить не могу...
вечером, в спокойной обстановке гляну...
как вменяемо получить индекс элемента из массива объектов, полученного по Get-ChildItem. Можете показать, как сие сделать? »
а зачем?! - индекс, чтобы по нему итерировать:
$aFiles = Get-ChildItem *.jpg -File
$iListFileNumber = 0
$iLimit = 8
$i = 0
while ($i -lt $aFiles.Length)
{
$sListName = "$($iListFileNumber.ToString('000000')).lst"
$iFileNumber = 0
while ($iFileNumber -lt $iLimit -and $i -lt $aFiles.Length)
{
$i = $iListFileNumber * $iLimit + $iFileNumber
Add-Content -Path $sListName -Value $aFiles[$i].Name
$iFileNumber+=1
}
$iListFileNumber+=1
}
польская нотация придумана, для имитации пользовательских типов - чтобы килограммы с километрами не складывать, а не для дублирования системных
боюсь, с группировкой отобранных файлов мне это не особо поможет. »
Не понял зачем там do ... until с рандомом, да и разбираться не стал...
Но, как минимум, тут:
$aFiles = Get-ChildItem -Path "$sSourceFolder\*.*" -File -Include '*.jpg', '*.jpeg', '*.jpe'
if($aFiles.Count -gt 0) {
$i = 0
foreach($oFile in $aFiles) {
Add-Member -InputObject $oFile -NotePropertyName Number -NotePropertyValue $i
$i++
}
$aFiles | Group-Object -Property { [Math]::Floor([System.Int32]$_.Number / $iLimit) }|...
действительно, есть лишнее действие (присвоение номеров элементам массива)...
Эквивалент:
$aFiles = Get-ChildItem -Path "$sSourceFolder\*.*" -File -Include '*.jpg', '*.jpeg', '*.jpe'
$aFiles | Group-Object -Property { [Math]::Floor($aFiles.name.indexof($_.name) / $iLimit) }
ух как тут жарко:)
спасибо большое за ответы. power shell конечно монструозный
что в .bat 10 строк, то в powershell целый том войны и мира
один вопрос
после формирования файла в list.txt есть куча строк с указанием файлов, из которых формируется видео.
выходное имя видео это то, что я задам, можно даже указать время сегодняшнее.
а нельзя ли, в качестве имени файла указать первую строчку и последнюю строчку list.txt?
допустим в папке лежат фото собачей будкии, а на выходе получилось не N.avi, а Будка злой собаки 01-01-2018_00h01m01s Будка злой собаки 01-01-2018_23h59m01s.avi
что в .bat 10 строк, то в powershell целый том войны и мира »
Это только так кажется... а на самом деле, powershell имеет значительно бОльшие возможности и инструменты, чем cmd, да и побыстрее работает, однако...
Например, прибавьте или отнимите, скажем, 7 дней к текущей дате в cmd, с учетом разного количества дней в месяцах, а также переход в новый/предыдущий месяц/год...
Вот, как это делается на powershell:
(get-date).adddays(7)
(get-date).adddays(-7)
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.