Войти

Показать полную графическую версию : [решено] for do copy создаёт лишний файл


shadowbat
28-09-2022, 09:34
есть два файла:
file.txt
file_2.txt

при запуске такого батника:

@echo off
chcp 1251
::for %%i in ("%CD%\*.txt") do (copy "%%i" "%%~dpni_new%%~xi")
for /R "%CD%" %%i in (*.txt) do (copy "%%i" "%%~dpni_new%%~xi")


создаётся не 2 файла, а 3. один из них лишний с двумя "_new"

file.txt
file_2.txt
file_2_new.txt
file_new.txt
file_new_new.txt


(если переименовать file_2.txt в zzz.txt, то ошибка пропадает и создаётся как и положено 2 файла)
(если в батнике поменять _new на -new, то ошибка пропадает и создаётся как и положено 2 файла)

в чём причина такой ошибки?

NickM
28-09-2022, 11:00
А какая задача то у Вас?
Или Вы думаете, что кто-нибудь поймёт её из Вашего кода сценария?

shadowbat
29-09-2022, 08:15
А какая задача то у Вас? »

задача - найти причину создания лишнего файла "_new"
если эта причина не будет найдена, то я поменяю "_new" на "-new" в коде и буду с этим жить

YuS_2
29-09-2022, 08:42
задача - найти причину создания лишнего файла "_new" »
При некоторых условиях (правильных по синтаксису, но неправильных для корректного кода), в цикле for может образоваться "лишняя" итерация. Как раз, для Вашего случая...
Вот, код, который наглядно отображает эту "лишнюю" итерацию:
@echo off
set /a f=5 &:число создаваемых файлов в каталоге
set /a k=0 &:динамический счетчик для наименований файлов
set /a n=0 &:динамический счетчик для подсчета итераций

rem Если отсутствует, создаем каталог TEXT, рядом со сценарием:
set "d1=%cd%\text"
if not exist "%d1%" md "%d1%"

cd "%d1%"
setlocal enabledelayedexpansion
rem Создаем тестовые файлы:
if not exist "*.txt" (
for /l %%i in (1,1,!f!) do rem: фигня>"!k!.txt"&set /a k+=1
)

rem Проверка лишней итерации в цикле:
echo.Файлов в каталоге:
dir /b/a-d
echo.--------------------------
echo.
echo.Переименование файлов циклом и собственно, "лишняя итерация":
for %%A in (*.txt) do (
echo %%A

rem Так проходов n+1 от количества файлов:
rename "%%A" "!random!.txt"

set /a n+=1
)
echo.
echo Проходов: !n!
echo.--------------------------
echo.
echo.Итоговое число файлов в каталоге:
dir /b/a-d
echo.
pause
Т.е. при наличии 5 текстовых файлов, цикл for выполняет 6 итераций...
Мораль: не выполняйте переименование файлов посредством цикла for, в одном и том же каталоге, где находятся исходные файлы. :)

megaloman
29-09-2022, 10:10
shadowbat, Если интересно не только "почему", но и "как", то@Echo Off
cls
>nul chcp 1251
For /R "%CD%" %%i in (*.txt) Do >nul (Echo %%i|FindStr /E /I "_new%%~xi" ||copy "%%i" "%%~dpni_new%%~xi")
pause
Exit /B

@Echo Off
cls
>nul chcp 1251
FOR /F "usebackq delims=" %%i IN (`2^>nul Dir "*.txt" /S /A:-D /B ^|FindStr /E /I /V "_new.txt"`) DO >nul copy "%%i" "%%~dpni_new%%~xi"
pause
Exit /B
При повторном запуске этих батников копий _new_new не будет, хотя минус - повторное копирование.
Поэтому лучше использовать xcopy /D@Echo Off
cls
>nul chcp 1251
FOR /F "usebackq delims=" %%i IN (`2^>nul Dir "*.txt" /S /A:-D /B ^|FindStr /E /I /V "_new.txt"`) DO Echo F|>nul xcopy /D "%%i" "%%~dpni_new%%~xi"
pause
Exit /B
Либо @Echo Off
cls
>nul chcp 1251
FOR /F "usebackq delims=" %%i IN (`2^>nul Dir "*.txt" /S /A:-D /B ^|FindStr /E /I /V "_new.txt"`) DO (
If Not Exist "%%~dpni_new%%~xi" >nul copy "%%i" "%%~dpni_new%%~xi"
)
pause
Exit /B

YuS_2
29-09-2022, 11:00
в чём причина такой ошибки? »
Как альтернативу cmd, лучше изучайте powershell, возможностей у него больше... а также, более понятный синтаксис и легче для запоминания.
Ваша задача, на powershell:
$folder = '.\TEST'
$filter = '*.txt'
$pattern = '_new'

dir $folder -filter $filter -file|%{
if($_ -notmatch $pattern){
copy $_.fullname ($_.directoryname + '\' + $_.basename + $pattern + $_.extension)
}
}

shadowbat
30-09-2022, 16:38
megaloman
YuS_2
благодарю за помощь




© OSzone.net 2001-2012