Я новичок в пакетных сценариях, и я хотел знать, можно ли перечислить объединенный размер всех файлов с типом в текстовом файле.
Например: если есть два файла .mp3
, каждый из 1GB
, вывод должен быть
MP3 2147483648 bytes
Я знаю, как перечислить все файлы в каталоге или просто перечислить файлы одного типа. Проблема, с которой я столкнулся, состоит в том, чтобы сложить вместе размеры одинаковых типов файлов.
Вот мой код:
@echo off
Rem This is for listing down all the files in the directory Program files
set mypath=%cd%
dir "%mypath%" *.mp3 > %mypath%\lists.txt
echo program completed
CMD.exe ограничен 32-битными целыми числами. Таким образом, вы можете добавить только до 2147483647 байт. Или по сути 2 Гигабайта. Так что это не лучшая задача для командных файлов.
Я бы предположил, что эта задача непростая для кого-то, кто плохо знаком с пакетным скриптингом, и предложу решение, которое вместо этого использует PowerShell
.
@Echo Off
Set "MyDir=%~1"
If Defined MyDir CD /D "%MyDir%" 2>Nul || Exit /B
Dir /B/A-D >Nul 2>&1 || Exit /B
(For /F "Skip=3 Tokens=1-2 Delims=. " %%A In ('PowerShell -NoP -NoL^
"GCI -Ex 'lists.txt' -Fo|?{!$_.PSIsContainer}|Group Extension|"^
"Select Name,@{n='TS';e = {(($_.Group|Measure Length -Sum).Sum)}}"
') Do Echo %%A %%B bytes)>"%__CD__%lists.txt"
С этим вы либо:
%~1
на ваш целевой каталог.или же:
Если ни один из них не будет выполнен, он должен произвести вывод для текущего каталога.
(Обратите внимание, что, поскольку выходной файл перезаписывает любой существующий в целевом каталоге, он будет включать старый размер в свои собственные результаты. По этой причине я добавил исключение (непроверенное) как часть команд PowerShell
)
PowerShell намного проще или почему вы предлагаете его как пакетную альтернативу? Также спасибо за решение.
@LuigiKraken, поскольку в вашем вопросе специально используется командный файл и он помечен как таковой, я предоставил решение, соответствующее вашему запросу! Если решение достигает намеченной цели, вам следует пометить его как принятое, щелкнув галочку слева от выбранного вами ответа.
Пока совокупный размер не превышает целочисленный предел (2 147 483 647),
эта небольшая партия может сделать:
:: Q:\Test\2018\05\01\SO_50117738.cmd
@Echo off & SetLocal
Pushd "C:\Test"
For /f "delims= = " %%A in ('2^>Nul Set Ext[') Do Set "%%A = "
For /f "delims = " %%A in ('Dir /B/A-D') Do Set /A "Ext[%%~xA]+=%%~zA/1024"
Set Ext[
Пример вывода теперь для целых килобайт (байты усечены)
> Q:\Test\2018\05\01\SO_50117738.cmd
Ext[.cmd]=0
Ext[.html]=2
Ext[.ps1]=11
Ext[.sh]=3
Ext[.txt]=3
Ext[.vbs]=0
Ext[]=0
> powershell -nop -nol "$ext=@{};ls -File|%{$ext.\"$($_.Extension)\"+=$_.Length};$ext"
Name Value
---- -----
.txt 4567
.ps1 12827
.vbs 435
.cmd 2000
.sh 4605
.html 3536
219
Еще один с немного большим контролем над выводом
> powershell -nop -nol "$ext=@{};ls -File|%{$ext.\"$($_.Extension)\"+=$_.Length};$ext.GetEnumerator()|sort Name|%{'{0,-6} {1,12}' -f $_.Name,$_.Value}"
219
.cmd 2000
.html 3536
.ps1 12827
.sh 4605
.txt 4567
.vbs 435
Если бы вопрос не начался с простого примера из двух файлов, который уже достиг предела или превышает его, я боюсь, что в данном случае это не решение, (что обидно из-за своей простоты). Было бы лучше, если бы вы попытались лучше воспроизвести требуемый результат, если эти ограничения больше не будут проблемой, или для будущих поисков.
Я знаю, что есть несколько чистых пакетных файлов, которые помогают превысить 32-битный целочисленный предел. Но, конечно, это делает ваш код намного длиннее. Я использовал некоторые сценарии Джудаго, но его веб-сайт больше не существует. Я не видел, чтобы он писал на StackOverFlow или DosTips.com несколько лет.
Что ж, mp3-файл размером 1 ГБ маловероятен, но вы правы - я изменю его для подсчета килобайт и добавлю вариант PowerShell того же алгоритма с хеш-таблицей.
Настроить пакетный код очень просто, чтобы в результате управлять любое количество цифр. Это решение позволяет управлять накопленными результатами до 16 цифр:
@echo off
setlocal EnableDelayedExpansion
set "digits=8"
rem Assemble the factor with the proper number of digits
set "factor=1"
for /L %%i in (1,1,%digits%) do set "factor=!factor!0"
rem Accumulate size of all extensions in 2 groups of %digits% digits each
for %%a in (*.*) do (
set "size=%factor%%%~Za"
set /A "low[%%~Xa]+=1!size:~-%digits%!-factor, carry=low[%%~Xa]/factor, low[%%~Xa]%%=factor"
set "size=%%~Za"
set "size=!size:~0,-%digits%!"
set /A "high[%%~Xa]+=carry+size"
)
rem Show results
for /F "tokens=2,3 delims=[.] = " %%a in ('set high[') do (
if %%b neq 0 (
set "low=%factor%!low[.%%a]!"
echo %%a %%b!low:~-%digits%! bytes
) else (
echo %%a !low[.%%a]! bytes
)
)
Пример вывода:
C:\Users\Antonio\Documents\tests> dir *.mp3
El volumen de la unidad C no tiene etiqueta.
El número de serie del volumen es: 0895-160E
Directorio de C:\Users\Antonio\Documents\tests
07/07/2010 09:58 a. m. 14,336,418 BigFile.mp3
01/05/2018 03:01 p. m. 143,364,180 BigFile2.mp3
01/05/2018 03:13 p. m. 1,433,641,800 BigFile3.mp3
07/07/2010 09:58 a. m. 14,336,418 BigFileB.mp3
4 archivos 1,605,678,816 bytes
0 dirs 390,478,827,520 bytes libres
C:\Users\Antonio\Documents\tests> test.bat
bat 200759 bytes
csv 20412 bytes
mp3 1605678816 bytes
pdf 62799 bytes
txt 1036041 bytes
Большое спасибо, это действительно помогает.
Могу я попросить вас поставить галочку рядом с этим ответом?
Хотя какую часть мне нужно изменить, чтобы изменить целевой каталог для ввода и вывода? Я хотя и заменил . на% cd%, но это просто сломало его: /.
Вопрос подразумевает, что вам нужен список, который показывает каждый тип файла в каталоге вместе с общим размером в байтах для этого конкретного типа файла. Однако ваш пример кода показывает только один тип файла и не пытается создать информацию, аналогичную вашему выходному примеру. Это не служба запроса кода, мы рады помочь вам с вашим кодом, но для этого ожидается, что предоставленный вами код попытается выполнить задачу, с которой вам требуется помощь.