I am writing a batch file to read all the files within the folder.
Below is my code:
#echo off
setlocal EnableDelayedExpansion
for %%I in (C:\test\*.print_job.*) do (
Set Name=%%~nxI
echo !Name!
)
pause
I am able to get all the .print_job files but now I want to read all the files and look for a specific identifier.
if the file contains "MOUNT" then move that file to C:\Folder1
if the file contains "PROD" then the file should get moved to
C:\Folder2
if the file contains "SPI" then the file should get moved to
C:\Folder3
Thanks in advance
#echo off
rem string target destination
call :movefiles "MOUNT" "C:\test\*.print_job.*" "C:\Folder1"
call :movefiles "PROD" "C:\test\*.print_job.*" "C:\Folder2"
call :movefiles "SPI" "C:\test\*.print_job.*" "C:\Folder3"
goto :eof
:movefiles
if not exist "%~3" md "%~3"
for /f "delims=" %%A in ('2^>nul findstr /l /m /c:"%~1" "%~2"') do (
move "%%~A" "%~3"
)
goto :eof
Use of call :movefiles to handle each of the 3 strings to
search for in the target files.
Call syntax: call :movefiles <string> <target> <destination>
Makes the destination directory if not exist. If string found
in a target file, the file will be moved into the destination
folder.
The findstr arguments used are:
/l Uses search strings literally.
/m Prints only the filename if a file contains a match.
/c:string Uses specified string as a literal search string.
You can insert rd "%~3" after the for loop if you want to
remove empty destination folders.
To loop every 2 seconds:
#echo off
:main
rem string target destination
call :movefiles "MOUNT" "C:\test\*.print_job.*" "C:\Folder1"
call :movefiles "PROD" "C:\test\*.print_job.*" "C:\Folder2"
call :movefiles "SPI" "C:\test\*.print_job.*" "C:\Folder3"
timeout /t 2 /nobreak >nul
goto :main
:movefiles
if not exist "%~3" md "%~3"
for /f "delims=" %%A in ('2^>nul findstr /l /m /c:"%~1" "%~2"') do (
echo move "%%~A" "%~3"
)
goto :eof
You may need to use Ctrl+C to end the script as it is in a continuous loop.
If you can use a task scheduler instead then that could work.
If a file name with the search word removed is different it had been in there.
#echo off
for %%I in (C:\test\*) do Call :Sub "%%I"
Pause
Goto :Eof
:Sub
Set "Name=%~nx1"
if "%Name%" neq "%Name:MOUNT=%" (move "%~1" "C:\Folder1\" & Goto :Eof)
if "%Name%" neq "%Name:PROD=%" (move "%~1" "C:\Folder2\" & Goto :Eof)
if "%Name%" neq "%Name:SPI=%" (move "%~1" "C:\Folder3\" & Goto :Eof)
Related
I have some PDF files that I need to rename and move to specific folders to be able to import into a system.
The file by default has the following name:
ex: 12345.123456/1234-12.pdf
First I need to remove the characters "," "/" "-"
#echo off
setlocal EnabledelayedExpansion
for /r "C:\importation" %%a in (*) do (
set "newname=%%~na"
set "newname=!newname:.=!"
set "newname=!newname:-=!"
set "newname=!newname:/=!"
ren "%%~a" "!newname!%%~xa"
)
Now I need to create folders with the filename (without the characters removed, ex: 12345123456123412) and rename them to the following pattern:
ex: P12345123456123412_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
For that I drag the files to the following script:
#If Not "%~1" == "" For %%G In (%*) Do #MD "%%~dpG%%~nG" 2>NUL && Move /Y "%%~G" "%%~dpG%%~nG\P%%~nG_V1_A0V0_T07-54-369-664_S00001_Volume%%~xG"
I would like to do only one process, that is, join the two scripts and run only once.
Can someone help me?
Rather than dragging the files to the batch file I would like to run it and have it read the files (.pdf) from the folder
Is something like this what you are looking for?
The following will accept drag and drop of one or more files or directories, (subject to command line length restrictions). Each individually dropped PDF file and each PDF file within any dropped directory should be processed as requested.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
If "%~1" == "" GoTo :EOF
For %%G In (%*) Do (For %%H In ("%%~G") Do If "%%~aH" Lss "-" (
Echo Error! %%G no longer exists.
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
) Else If "%%~aH" GEq "d" (For %%I In ("%%~G\*.pdf") Do Call :Sub "%%~I"
) Else If /I "%%~xG" == ".pdf" (Call :Sub "%%~G"
) Else (Echo Error! %%G is not a PDF
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL))
GoTo :EOF
:Sub
Set "basename=%~n1"
Set "basename=%basename:.=%"
MD "%~dp1%~n1" 2>NUL
If Not ErrorLevel 1 Move /Y %1 "%~dp1%~n1\P%basename:-=%_V1_A0V0_T07-54-369-664_S00001_Volume%~x1"
Exit /B
Please note, as the character / is invalid in file or directory names, I have ignored that part of your question.
I have some pdf's in a folder that I need to organize them like this:
PDF name: 123.12.123.pdf ; 102030_01.pdf; 102030_02.pdf; 123.4512.34561.23412.pdf
Now I need to create folders with the filename (without the characters removed, ex: 12345123456123412) and rename them to the following pattern: ex: P12345123456123412_V1_A0V0_T07-54-369-664_S00001.pdf
for this I have used the following code which works very well:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
If "%~1" == "" GoTo :EOF
For %%G In (%*) Do (For %%H In ("%%~G") Do If "%%~aH" Lss "-" (
Echo Error! %%G no longer exists.
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL
) Else If "%%~aH" GEq "d" (For %%I In ("%%~G\*.pdf") Do Call :Sub "%%~I"
) Else If /I "%%~xG" == ".pdf" (Call :Sub "%%~G"
) Else (Echo Error! %%G is not a PDF
%SystemRoot%\System32\timeout.exe /T 2 /NoBreak 1>NUL))
GoTo :EOF
:Sub
Set "basename=%~n1"
Set "basename=%basename:.=%"
MD "%~dp1%~n1" 2>NUL
If Not ErrorLevel 1 Move /Y %1 "%~dp1%~n1\P%basename:-=%_V1_A0V0_T07-54-369-664_S00001_Volume%~x1"
Exit /B
I drag the pdfs into the .bat and it does the adjustment.
It happens that there is a case that I am not able to handle. Some pdfs need to be in the same folder, for example in the following case:
PDF name: 102030_01.pdf; 102030_02.pdf;
Note that the pdfs have the same number, only after the _ that we have the difference. In this case you would need to create a folder with the name:102030
And move the two files into it, modifying their name as follows:
102030_01.pdf -> P102030_V1_A0V0_T07-54-369-664_S00001.pdf
102030_02.pdf -> P102030_V1_A0V0_T07-54-369-664_S00002.pdf
Could anyone help?
:Sub
Set "basename=%~n1"
Set "basename=%basename:.=%"
if /i "%basename%" neq "%basename:_=%" goto sub2
MD "%~dp1%~n1" 2>NUL
If Not ErrorLevel 1 Move /Y %1 "%~dp1%~n1\P%basename:-=%_V1_A0V0_T07-54-369-664_S00001_Volume%~x1"
Exit /B
:sub2
for /f "tokens=1*delims=_" %%b in ("%basename%") do (
MD "%~dp1%%b" 2>NUL
ECHO Move /Y %1 "%~dp1%%b\P%basename:-=%_V1_A0V0_T07-54-369-664_S000%%c_Volume%~x1"
)
Exit /B
Always test on dummy data first.
This code echoes the proposed move. After verification, remove the echo keyword to activate.
Caution: My reading of the code is that - should be removed from the basename in the new name, and that _Volume should be appended to the name part, which is not shown in your examples.
Essentially, if the basename contains _ then goto sub2.
sub2 partitions the name in basename, assigning the first part to %%b and the second to %%c (See for /? from the prompt for documentation)
Then the directory is created
The md will object if the directory already exists, hence the 2>nul in the original code (suppresses error messages)
If md found that error in the original then this appears to be a problem, so the move is not executed. In the new version, it is expected that the directory may already exist, so the errorlevel processing has been removed.
I know little to nothing about batch files so what I have is cut and paste of what I could find on the internet. What I am wanting to do is go through every text file in a folder. Copy everything after the word Customer(in every file customer only shows up once on the same line). Then make it a new txt file with only what I copied with the same name with a _Customer to distinguish it.
This is my current script. The problem with this is it only does one txt file at a time.
Current Script
#echo off
:start
cls
echo Quality Check
set /p PROGRAM= What is the CMM Report ID?:
goto create
:create
cls
SET InFile=C:\CMM\%PROGRAM%.txt
SET OutFile=C:\CMM\%PROGRAM%_Customer.txt
SET TempFile=Temp.txt
IF EXIST "%TempFile%" DEL "%TempFile%"
FOR /F "tokens=*" %%A IN ('FINDSTR /N "Customer" "%InFile%"') DO (
CALL :RemovePrecedingCustomer "%%A"
FOR /F "tokens=1 delims=:" %%B IN ('ECHO.%%A') DO (
MORE +%%B "%InFile%"> "%TempFile%"
FINDSTR /V "end" "%TempFile%">> "%OutFile%"
FOR /F "tokens=*" %%C IN ('FINDSTR "end" "%InFile%"') DO (
CALL :Removeend "%%C"
IF EXIST "%TempFile%" DEL "%TempFile%"
GOTO :eof
)
)
)
GOTO :confirm
:RemovePrecedingCustomer
SET String=%~1
SET String=%String:*Customer =%
ECHO.%String%> "%OutFile%"
GOTO :eof
:Removeend
REM Replace "end" with a character that we don't expect in text that we will then use as a delimiter ( in this case)
SET LastLine=%~1
SET LastLine=%LastLine:end='%
FOR /F "tokens=1 delims='" %%A IN ('ECHO.%LastLine%') DO ECHO.%%A>> "%OutFile%"
GOTO :eof
:confirm
cls
echo Program %PROGRAM% has been converted. Thank you
pause
goto :start
Any help is appreciated
I want the batch file to move files %3 number of times, how can I accomplish this?
%1 is the source folder
%2 is the destination folder
%3 is the number of files
%4 is the filter.
This is the best I could come up with but it doesn't seem to work consistently.
#echo off
SETLOCAL EnableDelayedExpansion
set movedFiles=0
if [%4] EQU [] goto regular
:special
for /R "%1" %%G in (%4) do (
echo moving "%4"... "%%G"
move /Y "%%G" "%2"
set /a movedFiles+="1"
if !movedFiles! EQU %3 GOTO endOfCopy
)
GOTO endOfCopy
:regular
for /R "%1" %%G in (*) do (
echo moving... "%%G"
move /Y "%%G" "%2"
set /a movedFiles+="1"
if !movedFiles! EQU %3 GOTO endOfCopy
)
:endOfCopy
echo Done, %movedFiles% files Where copied successfully
ENDLOCAL
Perhaps you could change your code a little, (and in the meantime see if it fixes your issue):
#Echo Off & SetLocal EnableExtensions DisableDelayedExpansion
If "%~4"=="" (Call :StartMove %* "*") Else Call :StartMove %*
Pause & GoTo :EOF
:StartMove
Set "Moved=0" & For /R "%~1" %%A In ("%~4") Do (SetLocal EnableDelayedExpansion
If !Moved! Equ %3 (EndLocal & Set "Moved=%Moved%" & GoTo EndMessage)
Echo ...Moving "%%A" & Move /Y "%%A" "%~2" >Nul 2>&1 && Set /A Moved +=1)
:EndMessage
Echo Done, %Moved% files were copied successfully & EndLocal & Exit /B
Please note that this code, like yours, does not verify input parameters, (whether they exist, are of the correct type, in the correct order etc), I'd suggest you implement something to do so, moving forward. Even adding something as simple as the following would be a start:
If Not Exist "%~1\" Exit /B
If Not Exist "%~2\" Exit /B
If "%~3"=="" Exit /B
Windows
Based on the post (dos batch iterate through a delimited string), I wrote a script below but not working as expected.
Goal: Given string "Sun,Granite,Twilight", I want to get each theme value in loop so that I can do some processing with the value.
Current output is not corrct:
list = "Sun,Granite,Twilight"
file name is "Sun Granite Twilight"
For the first iteration it should be:
list = "Sun,Granite,Twilight"
file name is "Sun"
Then second iteration should be "file name is "Granite" and so on.
What am I doing wrong?
Code:
set themes=Sun,Granite,Twilight
call :parse "%themes%"
goto :end
:parse
setlocal
set list=%1
echo list = %list%
for /F "delims=," %%f in ("%list%") do (
rem if the item exist
if not "%%f" == "" call :getLineNumber %%f
rem if next item exist
if not "%%g" == "" call :parse "%%g"
)
endlocal
:getLineNumber
setlocal
echo file name is %1
set filename=%1
endlocal
:end
This is the way I would do that:
#echo off
set themes=Sun,Granite,Twilight
echo list = "%themes%"
for %%a in ("%themes:,=" "%") do (
echo file name is %%a
)
That is, change Sun,Granite,Twilight by "Sun" "Granite" "Twilight" and then process each part enclosed in quotes in a regular (NO /F option) for command. This method is much simpler than an iterative for /F loop based on "delims=,".
I took Aacini's answer and only slightly modified it to remove the quotes, so that the quotes can be added or removed as it would be in the desired command.
#echo off
set themes=Hot Sun,Hard Granite,Shimmering Bright Twilight
for %%a in ("%themes:,=" "%") do (
echo %%~a
)
I made a few modifications to your code.
Need goto :eof at end of subroutines and at end of main routine so you don't fall into subroutines.
tokens=1* (%%f is first token; %%g is rest of the line)
~ in set list=%~1 to remove quotes so quotes don't accumulate
#echo off
set themes=Sun,Granite,Twilight
call :parse "%themes%"
pause
goto :eof
:parse
setlocal
set list=%~1
echo list = %list%
for /F "tokens=1* delims=," %%f in ("%list%") do (
rem if the item exist
if not "%%f" == "" call :getLineNumber %%f
rem if next item exist
if not "%%g" == "" call :parse "%%g"
)
endlocal
goto :eof
:getLineNumber
setlocal
echo file name is %1
set filename=%1
goto :eof
Looks like it needed the "tokens" keyword...
#echo off
set themes=Sun,Granite,Twilight
call :parse "%themes%"
goto :end
:parse
setlocal
set list=%1
for /F "delims=, tokens=1*" %%f in (%list%) do (
rem if the item exist
if not "%%f" == "" call :getLineNumber %%f
rem if next item exist
if not "%%g" == "" call :parse "%%g"
)
endlocal
goto :end
:getLineNumber
setlocal
echo file name is %1
set filename=%1
endlocal
:end