У меня есть файл .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?
cd /d "H:\ere is\the folder\containing the text file\"
и for /f "delims = " %%a in ('dir /a-d /b *.txt') do ...
Fmm
это set
неправильно. Это должно быть 4,2
, так как пакет определяет первый символ как символ 0. Вы определяете sn
как ноль, затем, если последний файл .txt
, найденный в каталоге, соответствует текущему месяцу, добавляя 1
к sn
, а если нет, вы устанавливаете sn
на 1 , Так что sn
всегда будет приобретать одно и то же число - 1
. Вы не говорите, должно ли sn
быть 1 или 2 цифрами, но вам, вероятно, нужно установить sn
на то, что следует за -
, затем добавить 1 — и, если для месяца нет совпадений имен файлов, начать с 1
. О, мой! такие возможности. Проще написать часть тот в качестве ответа...
Для этой задачи можно использовать следующий пакетный файл:
@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%"
наверное. Обратите внимание на пропущенные ~
и ,
не .
На самом деле это новый вопрос
верно, опечатка :)
Ваш синтаксис
for
отключен. Смотритеfor /?
. Чтобы оценить команду, вам нужен переключатель/f
."delims = "
было бы безопаснее, а командеdir
нужен переключатель/b
для вывода только имени и переключатель/a-d
для исключения имен папок. Также см. ответ npocmaca список безопасных методов для получения надежной и переносимой строки даты/времени.