I set up a batch (copy.bat) file in my Windows sendto Directory that is for Copying a bunch of files via rightclicking the directories and choosing sendto "copy.bat".
#echo off
setlocal enabledelayedexpansion
set cnt=0
set cur=0
:files
for /R "%~1" %%F in (*.7z, *.avi) do (set /a cnt+=1)
shift
if "%~1" NEQ "" goto :files
echo !cnt! files found for copying.
echo Processing ...
set "DEST_DIR=E:\"
:while
for /R "%~1" %%F IN (*.7z, *.avi) do (
if exist "%%F" (
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!%%~dpF:%%~1%=!
xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
)
set /a cur+=1
echo !cur!/!cnt! done...
)
shift
if "%~1" NEQ "" goto :while
pause
If I run the first for loop alone it counts the files.
If I run the second loop on its own it copies exatly those files the other loop is supposed to count.
However, both loops in one batch file will somehowe conflict. The Filecount works correctly but the copy process delivers an error: "The Path of is too long". Between "of" and "is" there is an additional Space. The final pause will correctly wait for button press. I assume it has to do something with the %%F variable, but renaming it in one of the loops does not help.
Please change the name of your .bat - copy is a keyword to cmd.
Your problem is that the first routine shifts out all of the parameters, so your second routine has no parameters to deal with.
The easiest way is probably:
set "DEST_DIR=E:\"
call :while %*
pause
goto :eof
:while
for /R "%~1" %%F IN (*.7z, *.avi) do (
...
if "%~1" NEQ "" goto while
goto :eof
which executes the second routine as en internal subroutine (the : in the call is required) providing that routine with a fresh copy of the parameter-list (%*)
You could also consider moving the if "~1"... to the start of the routine (just after the :while), change it to if "%~1" EQU "" goto :eof and change the final statement to goto while.
The label :eof is defined as end-of-file by cmd and should not be declared.
I'm trying to fill X files with chunks of content from a .txt file.
The thing is the .txt (source) file is small and I want my code to loop over it's content chunk by chunk and start again when no more chunks are avaliable until all files have been filled.
This is part of the (still on development) code. I've managed to teach my Batch.bat to recognized the chunks but I don't know how to check if I am at EOF to go back again to the begining.
Current code doesn't work since it has been simplified for the question (delayed expansion not present)
SET /A J=1
FOR /F "skip=%J% tokens=*" %%A IN (%~1%) DO (
CALL :CSV "%%A" %J%
)
EXIT /B
:CSV
SETLOCAL
IF NOT "%~1"=="---" (
ECHO %~1 >> Chistaco.txt
)
ENDLOCAL && SET /A J=%2+1
Code posted here is just a guide of my target, don't miss the question.
Thank you !
EDIT: Simplified Code Module
#ECHO OFF
SETLOCAL
REM Ask for parameters
SET /P filler=Enter the name of the file to use as filler (file.ext):
SET /P seed=Enter the seed of the files to fill:
CLS && ECHO %~1%
REM The variable "J" counts the lines to jump in "file.ext" (and btw, it cannot be 0 as the batch parses fails to read it)
REM This is where the EOF check is needed: "J" must be referenced outside the main loop so the script can loop inside "file.ext" untill all "seed???" files have been filled
SET /A J=1
FOR /R "%path%" %%X IN (%seed%*) DO ECHO %%X && CALL :FillerChomper "%filler%" "%%X"
ENDLOCAL
EXIT /B
:FillerChomper
SETLOCAL
FOR /F "skip=%J% tokens=*" %%A IN (%~1%) DO (
CALL :CSV "%%A" J %2%
IF "%%A"=="---" EXIT /B
)
EXIT /B
:CSV
SETLOCAL
IF NOT %1=="---" ECHO %~1 >> %~3%
ENDLOCAL && SET /A %2=%J%+1
EXIT /B
REM All functions must have a "EXIT /B" command or batch will just keep executing codelines until :EOF
Thank you guys for your help!
I have written a batch file which will get sql server named instance(mssqlserver\india) and the disk free space.
The content on file looks like this:
mssqlserver\India,D,20
mssqlserver\India,C,30
Now I have written a batch file to generate a html report based on the text file Result.txt. But my batch script is picking mssqlserver\India as a system location and is popping message for every entry in the text file, its moving to the next variable after I press enter key.
I want to ignore this message without any user interaction. Below is the script i am using:
#ECHO off
setlocal EnableDelayedExpansion
SETLOCAL
cd C:\Users
goto head >nul
:head
FOR /F "tokens=1-6 delims=," %%G IN (Result.txt) DO (
%%G%%H%%I
set temphost1=%%G
set temphost2=%%H
set temphost3=%%I
call :stripquotes %temphost1% %temphost2% %temphost3% >NUL
)
goto :end
:stripquotes
echo ^<tr bgcolor="#90EE90"^>^<td^>^%temphost1%^</td^>^<td^>^%temphost2%^</td^>^<td^>^%temphost3%^</td^>^</tr^>^ >> C:\Users\Report.html
:END
CLS
ECHO COMPLETED
PAUSE
With some #rem commented changes, next script could work:
#ECHO off
#rem EnableDelayedExpansion not applied in the code
#rem use enableextensions in the next line
setlocal EnableDelayedExpansion
#rem superabundant SETLOCAL
cd C:\Users
#rem Why "goto head >nul" as GOTO does not produce any output?
#rem And why next "goto head" at all?
goto head >nul
:head
FOR /F "tokens=1-6 delims=," %%G IN (Result.txt) DO (
#rem this caused the error message %%G%%H%%I
set temphost1=%%G
set temphost2=%%H
set temphost3=%%I
call :stripquotes
#rem this were superabundant and harmful %temphost1% %temphost2% %temphost3% >NUL
)
goto :end
:stripquotes
#rem some superfluous `^` carets removed from next line but the last one was harmful
echo ^<tr bgcolor="#90EE90"^>^<td^>%temphost1%^</td^>^<td^>%temphost2%^</td^>^<td^>%temphost3%^</td^>^</tr^> >> C:\Users\Report.html
#rem next line to return from the :stripquotes subroutine
goto :eof
:END
CLS
ECHO COMPLETED
PAUSE
I wrote this batch file to append some text to the filenames of a set of jpeg files, giving the option to append them before or after the current filename.
But for some odd reason when appending before the filename, one file is being proccessed twice getting the result as new_new_FileName.jpg while all other files are getting just new_FileName.jpg.
Interesting enough, this problem isn't happening always, as well as when appending after the filename it is always working fine.
Following is the entire code, with no visual difference between the before or after, but still resulting differently. Can anyone please examine this file and explain me where I'm wrong?
Help is appreciated.
#ECHO off
title Rename Script
set /A count=1
:Start
cls
set /p STR=choose a string to append:
cls
echo 1. Append before
echo 2. Append after
set /p choice=I choose (1,2):
if %choice%==1 goto renameb
if %choice%==2 goto renamea
:renameB
cls
echo Appending '%STR%' before current file name.
echo.
set /A count=0
FOR %%a in (*.jpg) DO (
ren "%%~a" "%STR%%%~na%%~xa"
echo Was: %%~a Became: %STR%%%~na%%~xa
set /A count+=1
)
goto end
:renameA
cls
echo Appending '%STR%' after current file name.
echo.
set /A count=0
FOR %%a in (*.jpg) DO (
ren "%%~a" "%%~na%STR%%%~xa"
echo Was: %%~a Became: %%~na%STR%%%~xa
set /A count+=1
)
goto end
:end
echo[
echo %count% files were renamed.
echo[
echo The process in now done.
pause
for renaming, the simple for loop doesn't work:
FOR %%a in (*.jpg) DO (
for some reasons from the old CP/M days with the FCB's a for /f loop is needed:
for /f "delims=" %%a in ('dir /a-d /b *.jpg') do (
i am writing a batch script monotonic file renamer. basically, it makes the titles of all the files 1 2 3 4 .... and so on. i have since expanded it to be able to handle files of different types (txt, doc, flv, etc) but not everything is working out.
my main concern is i have broken the delayed expansion calls i was making before. now using !var1! is never expanded, or never recognized as a variable.
here is a verbosely commented version of my script
::a monotonic file renamer
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET tempfile=temp.txt
SET exttemp=exttemp.txt
if [%1] == [] goto usage
::make sure your dont overwrite something useful
if EXIST %tempfile% (
ECHO Temp file already exists, are you sure you want to delete?
del /P %tempfile%
)
if EXIST %exttemp% (
ECHO EXT Temp file already exists, are you sure you want to delete?
del /P %exttemp%
)
::initialize
SET /a counter=0
SET type=
SET /a ender=%1
::write filenames to tempfile
DIR /B /ON > %tempfile%
::read lines one by one
for /f "usebackq delims=" %%a in (%tempfile%) do (
REM make sure we do not rename any of the working files
if NOT "%%a"=="renamer.bat" (
if NOT "%%a"=="temp.txt" (
if NOT "%%a"=="exttostr.bat" (
SET /a counter+=1
REM get file extension
exttostr %%a > %exttemp%
SET /P type= < %exttemp%
REM housekeeping
del /F %exttemp%
REM rename
ren %%a !counter!.!type!
ECHO Renamed "%%a" to "!counter!.!type!"
)))
REM exit when we have run enough
if "!counter!"=="!ender!" goto exit
)
goto exit
:usage
echo Usage: renamer NUMFILES
:exit
::final housekeeping
DEL temp.txt
the idea is i drop my two files, renamer.bat(this file) and exttostr.bat(helper to get the file extension) into the folder and run it, it will rename files sorted alphabetically from 1 to how ever many files i specify.
when i run the code, it never uses the variables marked for delayed expansion appropriately, always leaving them as "!varname!", so it renames the first file "!counter!.!type!" and throws errors for the rest because there is already a file in the directory with that name.
this brings me to a secondary issue. sorting the dir list alphabetically results in a poor handling of numbered files. for example the list:
"1 7 15 75 120"
is sorted:
"1 120 15 7 75"
i have not been able to find a way around this yet, only that it is indeed the intended result of the dir sort. the only workaround i have is padding numbers with enough zeroes in the front.
thanks in advance for any insight!
everything is sorted but the second problem. i think i have not spoken well. i have this issue when i take IN the directory file names, not when writing out. so they already need to be padded. i has hoping there was some other way to read the directory and have it be sorted appropriately.
the most promising thing i have found is here: http://www.dostips.com/DtCodeBatchFiles.php#Batch.SortTextWithNumbers
#ECHO OFF
if "%~1"=="/?" (
echo.Sorts text by handling first number in line as number not text
echo.
echo.%~n0 [n]
echo.
echo. n Specifies the character number, n, to
echo. begin each comparison. 3 indicates that
echo. each comparison should begin at the 3rd
echo. character in each line. Lines with fewer
echo. than n characters collate before other lines.
echo. By default comparisons start at the first
echo. character in each line.
echo.
echo.Description:
echo. 'abc10def3' is bigger than 'abc9def4' because
echo. first number in first string is 10
echo. first number in second string is 9
echo. whereas normal text compare returns
echo. 'abc10def3' smaller than 'abc9def4'
echo.
echo.Example:
echo. To sort a directory pipe the output of the dir
echo. command into %~n0 like this:
echo. dir /b^|%~n0
echo.
echo.Source: http://www.dostips.com
goto:EOF
)
if "%~1" NEQ "~" (
for /f "tokens=1,* delims=," %%a in ('"%~f0 ~ %*|sort"') do echo.%%b
goto:EOF
)
SETLOCAL ENABLEDELAYEDEXPANSION
set /a n=%~2+0
for /f "tokens=1,* delims=]" %%A in ('"find /n /v """') do (
set f=,%%B
(
set f0=!f:~0,%n%!
set f0=!f0:~1!
rem call call set f=,%%%%f:*%%f0%%=%%%%
set f=,!f:~%n%!
)
for /f "delims=1234567890" %%b in ("!f!") do (
set f1=%%b
set f1=!f1:~1!
call set f=0%%f:*%%b=%%
)
for /f "delims=abcdefghijklmnopqrstuwwxyzABCDEFGHIJKLMNOPQRSTUWWXYZ~`##$*_-+=:;',.?/\ " %%b in ("!f!") do (
set f2=00000000000000000000%%b
set f2=!f2:~-20!
call set f=%%f:*%%b=%%
)
echo.!f1!!f2!!f!,%%B
rem echo.-!f0!*!f1!*!f2!*!f!*%%a>&2
)
this code can sort the filenames with one number in them (i.e. video100.mov is fine, video100video10.mov would break it)
the issue i have is i think adding a call to this helper fn will break it again, so i will be trying to include this in my modified renamer.bat now. any help is appreciated.
Probably the batch for extracting the extension reset the local environment.
But, you don't need it. You may extract the extension with the ~x option. Something similar to this ....
:monotonicrename
set /a counter = 0
for %%a in (%1\*.*) do (
if exist %%~fa (
set /a counter += 1
echo ren %%~fa !counter!%%~xa
)
)
goto :eof
to include leading zeroes in the counter, so that the directory sorts correctly, replace the previous rename command with three lines
set zcounter=0000!counter!
set zcounter=!zcounter:~-4!
echo ren %%~fa !counter!%%~xa
So putting all pieces together, add the monotonicrename function you just created in the batch file that can be as simpler as...
#echo off
setlocal enabledelayedexpansion
call :monotonicrename %1
goto :eof
:monotonicrename
set /a counter = 0
for %%a in (%1\*.*) do (
if exist %%~fa (
set /a counter += 1
set zcounter=0000!counter!
set zcounter=!zcounter:~-4!
echo ren %%~fa !zcounter!%%~xa
)
)
goto :eof
I didn't experience any issues with delayed expansion, everything worked fine for me (except, of course, for the fact that I didn't have the exttostr.bat helper script.)
Anyway, there are several things that could be improved about your script:
You don't need to store the result of DIR into a file to read it afterwards. You can read the output directly in the FOR loop.
You don't need the helper batch script. The extension can be extracted from %%a by using the ~x modifier with the loop variable: %%~xa. You can read more about modifiers by issuing HELP FOR from the command prompt.
The renamer batch file's own name can be referenced in the script as %0. You can apply the ~n modifier where you only need to use the name without the extension. The combined modifier of ~nx will give you the name with the extension.
So, here's how your script might look like with the above issues addressed:
::a monotonic file renamer
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
IF [%1] == [] GOTO usage
::initialize
SET /A counter=0
SET type=
SET /A ender=%1
::read lines one by one
FOR /F "usebackq delims=" %%a IN (`DIR /B /ON`) DO (
REM make sure we do not rename any of the working files
IF NOT "%%~a"=="%~nx0" (
SET /A counter+=1
RENAME "%%~a" "!counter!%%~xa"
ECHO Renamed "%%~a" to "!counter!%%~xa"
)
REM exit when we have run enough
IF "!counter!"=="!ender!" GOTO :EOF
)
GOTO :EOF
:usage
ECHO Usage: %~n0 NUMFILES
As for your secondary issue, it can be easily resolved like this:
Use something like 100000 as counter's initial value. (Use however many 0s you like, but possibly no more than nine.) Add the same value to ender as well.
When renaming files, instead of !counter! use the expression that removes the first character (the 1): !counter:~1! (in fact, this is not about removal, but about extracting a substring starting from the offset of 1, learn more about it with the HELP SET command).
Here's the modified version of the above script:
::a monotonic file renamer
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
IF [%1] == [] GOTO usage
::initialize
SET /A counter=1000
SET type=
SET /A ender=%1
SET /A ender+=counter
::read lines one by one
FOR /F "usebackq delims=" %%a IN (`DIR /B /ON`) DO (
REM make sure we do not rename any of the working files
IF NOT "%%~a"=="%~nx0" (
SET /A counter+=1
RENAME "%%~a" "!counter:~1!%%~xa"
ECHO Renamed "%%~a" to "!counter:~1!%%~xa"
)
REM exit when we have run enough
IF "!counter!"=="!ender!" GOTO :EOF
)
GOTO :EOF
:usage
ECHO Usage: renamer NUMFILES
You can also see that I made some other enhancements, like making sure the file name is enclosed in double quotes, and using GOTO :EOF instead of GOTO exit (:EOF is a special pre-defined label that points at the end of the batch script so you don't need to define your own).