Как получить имя текстового файла, расположенного в текущем каталоге, в переменную с пакетным файлом

У меня есть файл .txt, имя которого используется в качестве ссылки с форматом AS2204-1 в соответствии со схемой именования ASyymm-sn, где yy — текущий год без века, mm — текущий месяц, а sn — порядковый номер с текущим месяцем. Я пытаюсь получить текущее имя файла и увеличить серийный номер на 1 в год и месяц без изменений, скопировать новое имя файла в буфер обмена, а затем переименовать текстовый файл.

Это мой код до сих пор:

@echo off
set yy=%date:~12,2%
set mm=%date:~4,2%
set /a sn=0

for %%a in ('dir *.txt') do (set filename=%%a)
set Fmm=%filename:~5,2%
if %Fmm%==%mm% (set /a sn=sn+1) else (set /a sn=1)
echo AS%yy%%mm%^-%sn% |clip 
ren "%filename%.txt"  "AS%yy%%mm%^-%sn%.txt"

Я не могу получить имя файла, присвоенное переменной filename.

Что не так с моим кодом и каким будет правильный цикл ЗА?

Ваш синтаксис for отключен. Смотрите for /?. Чтобы оценить команду, вам нужен переключатель /f. "delims = " было бы безопаснее, а команде dir нужен переключатель /b для вывода только имени и переключатель /a-d для исключения имен папок. Также см. ответ npocmaca список безопасных методов для получения надежной и переносимой строки даты/времени.

Stephan 03.04.2022 11:08

прежде всего спасибо за ваш ответ! причина, по которой мой синтаксис неверен, заключается в том, что я понятия не имею, что делаю. не могли бы вы написать правильный способ цикла for?

Avi Elishakov 03.04.2022 14:58
cd /d "H:\ere is\the folder\containing the text file\" и for /f "delims = " %%a in ('dir /a-d /b *.txt') do ...
Stephan 03.04.2022 17:30
Fmm это set неправильно. Это должно быть 4,2, так как пакет определяет первый символ как символ 0. Вы определяете sn как ноль, затем, если последний файл .txt, найденный в каталоге, соответствует текущему месяцу, добавляя 1 к sn, а если нет, вы устанавливаете sn на 1 , Так что sn всегда будет приобретать одно и то же число - 1. Вы не говорите, должно ли sn быть 1 или 2 цифрами, но вам, вероятно, нужно установить sn на то, что следует за -, затем добавить 1 — и, если для месяца нет совпадений имен файлов, начать с 1. О, мой! такие возможности. Проще написать часть тот в качестве ответа...
Magoo 03.04.2022 17:56
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
37
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Для этой задачи можно использовать следующий пакетный файл:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "tokens=1,2 delims=/" %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do set "YearMonth=%%G%%H" & goto SearchFile
:SearchFile
set "SerialNumber=0"
set "FileNameScheme=AS%YearMonth:~2%-"
for %%G in ("%FileNameScheme%*.txt") do for /F "tokens=2 delims=-" %%H in ("%%~nG") do if %%H GTR !SerialNumber! (set "SerialNumber=%%H" & set "FileName=%%G")
set /A SerialNumber+=1
echo %FileNameScheme%%SerialNumber%| %SystemRoot%\System32\clip.exe
if defined FileName (
    ren "%FileName%" "%FileNameScheme%%SerialNumber%.txt"
) else (
    rem del /Q "AS????-*.txt" >nul 2>nul
    echo %FileNameScheme%%SerialNumber%>"%FileNameScheme%%SerialNumber%.txt"
)
endlocal

Первые две строки полностью определяют требуемую среду выполнения:

  • режим эха команд выключен
  • расширения команд включены
  • расширение переменной с задержкой включено

Пожалуйста, прочитайте главу Использование ROBOCOPY для получения текущей даты/времени в моем ответе на Время установлено неправильно после полуночи для объяснения командной строки ЗА, которая использует РОБОКОПИЯ для получения текущего года и месяца независимо от того, какая страна (регион) настроена для используемой учетной записи, которая определяет формат даты динамической переменной DATE .

Переменная среды SerialNumber определяется первой со значением по умолчанию 0.

Переменная среды FileNameScheme определяется с помощью AS в начале, текущего года без века всегда с двумя цифрами, текущего месяца с всегда двумя цифрами и -, что приводит сегодня к строке AS2204-.

Команда ЗА используется для поиска в Текущий каталог (можно в любом каталоге) одного или нескольких нескрытых файлов, соответствующих шаблону подстановки AS2204-*.txt.

Непонятно, как мои файлы могут находиться в текущем каталоге, соответствующем подстановочному шаблону AS????-*.txt. Поэтому код написан для работы с несколькими файлами, соответствующими этому шаблону подстановки, в текущем каталоге.

Для каждого имени файла, соответствующего подстановочному шаблону с уже включенными текущими годом и месяцем, используется еще один цикл ЗА, чтобы получить строку между дефисом и расширением файла, которое, как мы надеемся, всегда является числом в диапазоне от 0 до 2147483647 без начальных нулей.

Эта числовая строка сравнивается с текущим значением переменной среды SerialNumber. Из-за этого сравнения чисел необходимо включить отложенное развертывание переменных. Если номер текущего файла больше текущего серийного номера, большее число используется в качестве серийного номера, а имя текущего файла присваивается переменной среды FileName.

Обратите внимание, что GTR не работает с числом в файле, имеющим начальный ноль, так как в этом случае число будет интерпретироваться как восьмеричное, а не как десятичное число, что означает, что 08 и 09 будут интерпретироваться как недопустимые восьмеричные числа с использованием в этом случае значения 0 для сравнения чисел.

Значение по умолчанию 0 или наибольшее количество файлов, соответствующих AS2204-*.txt, затем увеличивается на единицу с помощью арифметического выражения.

Имя файла с увеличенным серийным номером копируется без расширения файла в буфер обмена для любой цели.

Если действительно был найден файл с текущим годом и месяцем в имени, то этот файл теперь переименовывается, чтобы содержать порядковый номер, увеличенный на единицу. В противном случае создается новый файл с новым именем файла, содержащий имя файла без расширения в качестве данных, например AS2204-1.

Существует строка, закомментированная командой РЭМ, которая удалит все файлы, соответствующие подстановочному шаблону AS????-*.txt, за исключением скрытых файлов, игнорируемых командой ДЕЛ по умолчанию, и файлов только для чтения, которые не удаляются командой ДЕЛ по умолчанию, и соответствующих файлов, открытых в данный момент командой приложение. Непонятно, что делать с другими файлами, соответствующими этому шаблону, за предыдущие месяцы.

Код пакетного файла может быть оптимизирован для следующих командных строк, если в текущем каталоге либо нет, либо всегда есть только один файл, соответствующий шаблону подстановки AS????-*.txt:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=1,2 delims=/" %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do set "YearMonth=%%G%%H" & goto SearchFile
:SearchFile
set "SerialNumber=0"
set "FileNameScheme=AS%YearMonth:~2%-"
for %%G in ("%FileNameScheme%*.txt") do for /F "tokens=2 delims=-" %%H in ("%%~nG") do set "SerialNumber=%%H"
set /A SerialNumber+=1
echo %FileNameScheme%%SerialNumber%| %SystemRoot%\System32\clip.exe
if exist "AS????-*.txt" (
    ren "AS????-*.txt" "%FileNameScheme%%SerialNumber%.txt"
) else (
    echo %FileNameScheme%%SerialNumber%>"%FileNameScheme%%SerialNumber%.txt"
)
endlocal

Расширение переменной с задержкой больше не требуется, что немного ускоряет обработку командного файла. Серийные номера с одним или несколькими ведущими нулями по-прежнему будут проблемой, потому что команда НАБОР при оценке арифметического выражения также преобразует числовую строку в целое число с интерпретацией числа как восьмеричного числа при наличии символа 0 в начале числовой строки.

Чтобы понять, какие команды используются и как они работают, откройте окно командная строка, выполните в нем следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • del /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • rem /?
  • robocopy /?
  • set /?
  • setlocal /?

Смотрите также:

Ответ принят как подходящий
@echo off
setlocal
pushd "?:\whichever\directory\contains your\target files"
set "yy=%date:~12,2%"
set "mm=%date:~4,2%"

set "filename = "    
for /f %%a in ('dir /b /a-d /od AS%yy%%mm%-*.txt 2^>nul') do (set "filename=%%~na")
rem use this line if you use suppressed leading zero
if defined filename (set /a "sn=%filename:*-=%+1") else (set /a sn=1)
rem use this line if you use 2-digit
if defined filename (set /a "sn=1%filename:~-2%+1") else (set /a sn=101)

IF %sn% gtr 100 SET "sn=%sn:~-2%"

echo AS%yy%%mm%-%sn%
ren "whatever.txt"  "AS%yy%%mm%-%sn%.txt"
POPD
goto :eof

setlocal гарантирует, что изменения среды (новые переменные) будут удалены, когда пакет завершится.

pushd переключается в указанный каталог. Я понятия не имею, какой у вас каталог.

Синтаксис SET "var=value" (где значение может быть пустым; в этом случае var становится неопределенный) используется для обеспечения того, чтобы любые случайные пробелы в конце НЕ включались в назначенное значение.

for /f по очереди назначает каждую строку dir «отчета» %%a. В результате filename будет установлена ​​только часть имени (%%~na) найденного имени файла. dir /b создает список файлов для обработки в базовой форме (только имя файла). /a-d исключает имена каталогов, /od создает список в порядке дат. Маска файла AS%yy%%mm%-*.txt запрашивает все .txt файлы, которые соответствуют AS+номеру текущего года+номеру текущего месяца+-, поэтому нет необходимости проверять часть года/месяца. 2^>nul подавляет сообщения об ошибках, если не найдено имя файла, соответствующее маске.

Если имя файла было найдено, будет определено filename. Вот почему для него установлено значение ничего (которое определяет ООН) перед циклом for.

Имена файлов должны быть созданы в порядке даты, потому что ASyymm-10 будет сортировать доASyymm-2 в списке порядка имен по умолчанию.

Ну, я понятия не имею, используете ли вы 1- или 2-значные серийные номера - обработка отличается.

Если вы используете первый if defined..., то sn устанавливается на 1 больше, чем (та часть filename, которая существует, когда удаляются все символы до -) или 1, если предыдущий файл не был найден.

Если вы используете второй if defined..., то sn устанавливается на 1 больше, чем (1 + последние 2 символа filename) или 101, если предыдущий файл не был найден, поэтому ASyymm-07 выдаст sn=108. Это необходимо, потому что пакет интерпретирует числовую строку, начинающуюся 0 как ВОСЬМЕРИЧНЫЙ в вычислениях.

если результат> 100, используйте последние 2 символа sn.

Я только что echoвывел нужную строку на экран. Эхо в буфер обмена, если хотите.

Ну и переименовать. Непонятно, какой файл нужно переименовать в вычисляемое имя, поэтому я использовал whatever. Возможно, это файл с именем ASyymm.txt — если да, замените whatever на AS%yy%%mm%.

Popd возвращается в исходный каталог.

Документацию можно получить, выполнив commandname /? для большинства команд, но иногда это может быть немного загадочно. Просто найдите SO для примеров.

прежде всего спасибо за все ответы! Я сделал это таким образом - он работает нормально, пока часть переименования просто не работает - есть идеи, почему?

set "yy=%date:~12,2%"
set "mm=%date:~4,2%"

set "filename=\root\*.txt"

for %%A in (%filename%) do (set x=%%~nA)

set Fmm=%x:~4,2%
set sn=%x:7.1%

if %Fmm%==%mm% (set /a sn=sn+1) else (set /a sn=1)


echo AS%yy%%mm%^-%sn% |clip

set newfilename=AS%yy%%mm%-%sn%.txt
set oldfilename=%x%.txt

ren %oldfilename% %newfilename%
set sn=%x:7.1% должно быть set "sn=%x:~7,1%" наверное. Обратите внимание на пропущенные ~ и , не .
Magoo 04.04.2022 09:25

На самом деле это новый вопрос

entio 04.04.2022 10:14

верно, опечатка :)

Avi Elishakov 04.04.2022 10:58

Другие вопросы по теме