Показать полную графическую версию : [решено] Получить список файлов
UnrealMalcolm
06-06-2020, 13:51
Всем добрый день.
Уважаемые форумчане, не поможете ли вы в написании небольшого скриптика на .bat
К сожалению я в нём почти ничего не понимаю :(
Суть вот в чём. Скажем в папке C:/info/ есть следующие файлы: file1.format, file2.format, file3.format, file4.format и т.д.
Нужно сначала получить список всех файлов и присвоить каждому номер. Выводится через echo должно так:
1 - file1.format
2 - file2.format
3 - file3.format
4 - file4.format
Далее я нахожу нужный мне файл и вписываю его номер через set /p my_file="-> ". В итоге если я выбрал, скажем, file3.format, то я пишу "3" и переменная my_file становится file3.format.
Только вот как всё это записать правильно, я не знаю.
Уточню некоторые моменты:
1 - файлов может быть много
2 - могут отличатся количеством символов
3 - названия на английском языке
4 - в названиях имеются спец символы, а именно "_" и "-"
5 - начало файлов состоит из цифр (но это не точно, в будущем может и с букв начинаться )
В теории, я думаю должно работать всё как-то так:
1 - попадаем в папку
2 - переименовываем все файлы в алфавитном порядке(0-9 / a-z) из "file1" -> "1 - file1", "file2" -> "2 - file2" и т.д.
3 - выводим список всех файлов через echo
4 - задаём переменную my_file
5 - по всем файлам ищем начало как в my_file.
6 - запоминаем в другую переменную название файла
7 - переименовываем все обратно(убираем "1 -", "2 -" и т.д.)
8 - убираем n-ое кол-во символов(аля "1 -" 3 символа или "55 -" 4 символа) в переменной и получаем собственно то, что мне надо.
Хотя я думаю можно всё проще сделать. Но, как я уже сказал, я сам это никак не сделаю :(
Давайте потренируемся:
Зачем? «…и переменная my_file становится file3.format» не является ответом на данный вопрос.
Что делать, если файлов больше десяти? Больше десяти тысяч?
В каталоге присутствуют ещё какие-либо файлы?
UnrealMalcolm
06-06-2020, 16:00
Iska,
1. Переменная содержит название файла. Этот файл будет использоваться в строке запуска. Аля "start prog.exe -%my_file%"
2. Больше 1000 вряд ли будет, но больше 100 запросто. А что делать? Так же выводить их в консоль. Так как имена будут в алфавитном порядке, то найти нужный даже при 500 будет не проблемой.
3. Нет.
Давай те немного раскрою карты.
Есть код:
For /f "tokens=1-3 delims=/." %%a in ('date /t') do (set mydate=%%a-%%b-%%c)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a-%%b)
set day=%mydate:~0,2%
set month=%mydate:~3,2%
set year=%mydate:~6,4%
set record=%year%-%month%-%day%_%mytime%
Переменная record будет кое где в коде использоваться, в результате чего будут создаваться файлы формата %year%-%month%-%day%_%mytime%-кое_что_ещё
Как можно понять, сортировка будет такая: год-месяц-день-время, а значит, при алфавитной сортировке старые файлы будут верху, а новые - снизу. В общем сколько бы их не было, там сложно будет потеряться.
Как я говорил ранее, задача состоит в том, чтобы каждому файлу в папке присвоить номер, при выборе которого создавалась переменная, значение которой было бы названием этого самого файла.
megaloman
06-06-2020, 16:19
UnrealMalcolm, А что делать? »
Выбирайте файл через GUI@Echo Off
Cls
For /f "tokens=2 delims=:" %%i in ('chcp') do (Set "sPrevCP=%%i" &>nul Chcp 1251)
For /f "usebackq delims=" %%i in (
`@"mshta.exe" "about:<FORM><INPUT type='file' name='qq'></FORM><script>document.forms[0].elements[0].click();var F=document.forms[0].elements[0].value;try {new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(F)};catch (e){};close();</script>"`
) Do Set "sFileName=%%i"
>nul Chcp %sPrevCP%
if Defined sFileName (Echo Выбран файл: "%sFileName%") Else (Echo Файл не был выбран)
Pause
Exit /B 0
И только на рассвете, когда дописаны были последние строки, я вспомнил, что этот стих уже написал А. Пушкин. Такой удар со стороны классика!
UnrealMalcolm
06-06-2020, 17:00
megaloman, в целом, решение не плохое! Спасибо!
Правда не могли бы вы ещё мне помочь, как сделать, чтоб окно выбора файла открывалось в определенной директории? И как сделать, чтоб переменная имела не путь до файла, а только его название?
Хотя конечно решение без mshta.exe тоже было бы не плохо. Всё же хочется задействовать минимум программ.
megaloman
06-06-2020, 17:52
чтоб окно выбора файла открывалось в определенной директории »Пока не знаю. Однако, после скрипта последний путь запоминается в системе.И как сделать, чтоб переменная имела не путь до файла, а только его название »@Echo Off
Cls
For /f "tokens=2 delims=:" %%i in ('chcp') do (Set "sPrevCP=%%i" &>nul Chcp 1251)
For /f "usebackq delims=" %%i in (
`@"mshta.exe" "about:<FORM><INPUT type='file' name='qq'></FORM><script>document.forms[0].elements[0].click();var F=document.forms[0].elements[0].value;try {new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(F)};catch (e){};close();</script>"`
) Do Set "FileName=%%~nxi" &Set "PathFileName=%%~dpi"
>nul Chcp %sPrevCP%
if Defined FileName (Echo Выбран файл: "%FileName%" "%PathFileName%") Else (Echo Файл не был выбран)
Pause
Exit /B 0
UnrealMalcolm
06-06-2020, 18:35
Пока не знаю. Однако, после скрипта последний путь запоминается в системе. »
Тогда, к сожалению, такой вариант не подойдёт. Нужно чтоб сразу работа производилась в нужной директории.
UnrealMalcolm
07-06-2020, 00:11
В общем я своего добился. Правда получился какой-то говно код, но он работает. Единственный косяк - долго работает цикл. В целом за секунд 10 он покажет ~500 файлов. Но всё же хотелось бы что это было моментально.
Сам код получился таким:
@Echo Off
set file=11122.txt
dir /b /a-d "C:\Users\Admin\Desktop\ttt\*" > %file%
for /f "usebackq" %%S in (`find /c /v ""^<"%file%"`) do (set /a last_number=%%S)
set num=1
:start_add_pref
for /f "tokens=*" %%i in ('more +%num% "%file%"') do (echo %num% - %%i&goto next)
:next
set /a num=%num%+1
if %num%==%last_number% (goto:end_add_pref) else (goto:start_add_pref)
:end_add_pref
set /p file_select="-> "
for /f "tokens=*" %%i in ('more +%file_select% "%file%"') do (set my_file=%%i&goto final)
:final
del "%file%" 2>NUL
echo my file is %my_file%
pause
Если всё же кто-то подскажет как его ускорить - буду благодарен. Если нет, то "и так сойдёт".
Если всё же кто-то подскажет как его ускорить… »
Не очень понял Ваш код.
@echo off
setlocal enableextensions enabledelayedexpansion
set sSourceFolder=C:\Users\Admin\Desktop\ttt
>nul 2>&1 pushd "%sSourceFolder%" && (
set /a iCount = 0
echo ---------------------------------------------
for /f "usebackq delims=" %%i in (`2^>nul dir /b /a:-d "*.*"`) do (
set /a iCount += 1
set sCount= !iCount!
set "aChoice!iCount!=%%~i"
echo !sCount:~-6!. %%~i
)
echo ---------------------------------------------
set /p sChoice=Enter number of file:
echo.
popd
) || (
echo Can't find folder [%sSourceFolder%].
exit /b 1
)
if defined aChoice%sChoice% echo [!aChoice%sChoice%!]
endlocal
exit /b 0
Если без выравнивания — можно и короче.
UnrealMalcolm
07-06-2020, 11:05
Iska, супер! Прям что нужно, спасибо! Правда до последнего хотел избегать setlocal, но что поделать...
UnrealMalcolm
07-06-2020, 11:56
И ещё вопрос, как лучше использовать
setlocal enableextensions enabledelayedexpansion
?
В начале .bat файла и без endlocal или перед началом данного скрипта с закрытием endlocal?
.bat файл большой, там ещё много всего. Но нигде не используется setlocal и так же нет call функции.
Ещё немного упростил ваш скрипт, не очень понял зачем создавались некоторые функции и строки.
@echo off
setlocal enableextensions enabledelayedexpansion
set work_folder=%userprofile%\documents\Files
set /a prefix = 0
echo ---------------------------------------------
for /f "usebackq delims=" %%i in (`2^>nul dir /b /a:-d "%work_folder%\*.*"`) do (
set /a prefix += 1
set "choice!prefix!=%%~i"
echo !prefix! - %%~i
)
echo ---------------------------------------------
set /p file_number=Enter file number:
echo.
if defined choice%file_number% set my_file=!choice%file_number%:~17,-4!
echo %prefix%
echo %my_file%
endlocal
как лучше использовать setlocal enableextensions enabledelayedexpansion? В начале .bat файла и без endlocal или перед началом данного скрипта с закрытием endlocal?»
Лучше использовать по назначению.
megaloman
07-06-2020, 14:48
UnrealMalcolm, По идее мне не нравится идея :) : 500 файлов промелькнёт на экране мигом, а как номер выбирать? Я наваял вывод квантами, например, по 30 штук. В принципе, количество выводимых за раз строк можно поставить 100000, и получится как у Iska@Echo Off
Cls
Set "BoxIn=E:\_Скопировано.wd\201309_Испания_Барселона"
Set /A Quota=30
Set /A N=0
FOR /F "usebackq delims=" %%f IN (`2^>nul Dir "%BoxIn%\" /b /A:-d`) DO (
Set /A N+=1
Call Set "Num=$$$$$$%%N%%"
Call Set "%%Num:~-5%%=%%~nxf"
)
Set /A iN=0
Set "MyName="
FOR /F "usebackq tokens=1* delims==" %%i IN (`2^>nul Set "$"`) DO Set "Num=%%i" &Call :OutName "MyName" "%%Num:$= %%" "%%~nxj" ||GoTo :End
:End
If Not "%MyName%"=="" (Echo "%MyName%") Else (Echo File not selected)
Pause
Exit /B
:OutName
Set /A iN+=1
Echo %~2 %~3
If %iN% EQU %Quota% Call :MyPause %1 %2 %3 ||Exit /B 1
If %iN% EQU %N% Call :MyPause %1 %2 %3 ||Exit /B 1
Exit /B 0
:MyPause
Set /A iN=0, jN=0
Set /P jN=Type number 1-%N% of file, or Q-Quit, or Enter or any key to continue:
If /I "%jN%"=="Q" Exit /B 2
Set /A jN=jN*1
If %jN% EQU 0 Exit /B 0
If 1 LEQ %jN% If %jN% LEQ %N% (GoTo :Rezult) Else (Echo Wrong number %jN% &GoTo :MyPause)
:Rezult
Set "jN=$$$$$$%jN%"
Call Set "jN=%%%jN:~-5%%%"
Call Set "%~1=%%jN%%"
Exit /B 1
, а как номер выбирать? »
Прокручивать. Если мне не изменяет память, там окно в три тысячи строк. Хотя могу и ошибаться. Проверять, сбрасывая на умолчания, не хочу.
megaloman
07-06-2020, 16:10
UnrealMalcolm, Прокручивать. Если мне не изменяет память, там окно в три тысячи строк. Хотя могу и ошибаться. Проверять, сбрасывая на умолчания, не хочу. »Если это Вас устраивает, вот мой вариант без разбиения на экраны:@Echo Off
Cls
Set "BoxIn=E:\_Скопировано.wd\201309_Испания_Барселона"
Set /A N=0
FOR /F "usebackq delims=" %%f IN (`2^>nul Dir "%BoxIn%\" /b /A:-D`) DO (
Set /A N+=1
Call Set "Num=$$$$$$%%N%%"
Call Set "Num=%%Num:~-5%%"
Call Echo %%Num:$= %% %%~nxf
Call Set "%%Num%%=%%~nxf"
)
Set /P jN=Type number 1-%N% of file:
Set "Num=$$$$$$%jN%"
Set "MyName="
If 1 LEQ %jN% If %jN% LEQ %N% Call Set "MyName=%%%Num:~-5%%%"
If Not "%MyName%"=="" (Echo %Num:$= %="%MyName%") Else (Echo File %jN% not selected)
Pause
Exit /B
UnrealMalcolm
07-06-2020, 16:47
megaloman, спасибо за предложенный вариант, но я уже остановился на варианте Iska.
Немного под себя переделал, добавил пару проверок на наличие папки, файлов, ввода корректного номера файла и т.д. Всё работает отлично.
Наверное последнее чего я не понял, как обработать вывод "%%~i".
for /f "usebackq delims=" %%i in (`2^>nul dir /b /a:-d "%my_folder%\*.*"`) do (
set /a prefix += 1
set "choice!prefix!=%%~i"
echo !prefix! - %%~i
)
Как мне в строке "echo !prefix! - %%~i" - обработать %%~i чтоб убрать формат? Т.е. нужно как-то прицепить вот эту штуку -> :~0,-4, чтобы убрать с конца 4 символа. А так всё супер.
EDIT: это было просто, вчера голова уже совсем не сображала.
set file_tmp=%%~i
echo !prefix! - !file_tmp:~0,-4!
Всем спасибо кто помогал, на этом всё.
/close
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.