Компьютерный форум 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=345455)

UnrealMalcolm 06-06-2020 13:51 2924170

Получить список файлов
 
Всем добрый день.

Уважаемые форумчане, не поможете ли вы в написании небольшого скриптика на .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 символа) в переменной и получаем собственно то, что мне надо.

Хотя я думаю можно всё проще сделать. Но, как я уже сказал, я сам это никак не сделаю :(

Iska 06-06-2020 15:02 2924186

Давайте потренируемся:
  1. Зачем? «…и переменная my_file становится file3.format» не является ответом на данный вопрос.
  2. Что делать, если файлов больше десяти? Больше десяти тысяч?
  3. В каталоге присутствуют ещё какие-либо файлы?

UnrealMalcolm 06-06-2020 16:00 2924198

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 2924201

UnrealMalcolm,
Цитата:

Цитата 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 2924211

megaloman, в целом, решение не плохое! Спасибо!

Правда не могли бы вы ещё мне помочь, как сделать, чтоб окно выбора файла открывалось в определенной директории? И как сделать, чтоб переменная имела не путь до файла, а только его название?


Хотя конечно решение без mshta.exe тоже было бы не плохо. Всё же хочется задействовать минимум программ.

megaloman 06-06-2020 17:52 2924218

Цитата:

Цитата UnrealMalcolm
чтоб окно выбора файла открывалось в определенной директории »

Пока не знаю. Однако, после скрипта последний путь запоминается в системе.
Цитата:

Цитата UnrealMalcolm
И как сделать, чтоб переменная имела не путь до файла, а только его название »

Код:

@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 2924220

Цитата:

Цитата megaloman
Пока не знаю. Однако, после скрипта последний путь запоминается в системе. »

Тогда, к сожалению, такой вариант не подойдёт. Нужно чтоб сразу работа производилась в нужной директории.

UnrealMalcolm 07-06-2020 00:11 2924248

В общем я своего добился. Правда получился какой-то говно код, но он работает. Единственный косяк - долго работает цикл. В целом за секунд 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

Если всё же кто-то подскажет как его ускорить - буду благодарен. Если нет, то "и так сойдёт".

Iska 07-06-2020 03:40 2924251

Цитата:

Цитата UnrealMalcolm
Если всё же кто-то подскажет как его ускорить… »

Не очень понял Ваш код.

Скрытый текст
Код:

@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 2924261

Iska, супер! Прям что нужно, спасибо! Правда до последнего хотел избегать setlocal, но что поделать...

UnrealMalcolm 07-06-2020 11:56 2924266

И ещё вопрос, как лучше использовать

Код:

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


Iska 07-06-2020 13:44 2924282

Цитата:

Цитата UnrealMalcolm
как лучше использовать setlocal enableextensions enabledelayedexpansion? В начале .bat файла и без endlocal или перед началом данного скрипта с закрытием endlocal?»

Лучше использовать по назначению.

megaloman 07-06-2020 14:48 2924294

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


Iska 07-06-2020 15:10 2924296

Цитата:

Цитата megaloman
, а как номер выбирать? »

Прокручивать. Если мне не изменяет память, там окно в три тысячи строк. Хотя могу и ошибаться. Проверять, сбрасывая на умолчания, не хочу.

megaloman 07-06-2020 16:10 2924299

UnrealMalcolm,
Цитата:

Цитата Iska
Прокручивать. Если мне не изменяет память, там окно в три тысячи строк. Хотя могу и ошибаться. Проверять, сбрасывая на умолчания, не хочу. »

Если это Вас устраивает, вот мой вариант без разбиения на экраны:
Код:

@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 2924303

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

Iska 07-06-2020 19:58 2924328

Код:

%%~ni


Время: 07:51.

Время: 07:51.
© OSzone.net 2001-