I have been trying to create a script that check file name, if positive, then rename it and move it to a folder in a server, then check for next argument and do the same thing.
The complete idea is that, I have a system that produces CSV files, the name of the file is generated depending of the area, if I am in Nursing, it will generate a file with the word "Nursing" somewhere, so this will help me for scripting purposes to recognise where to put this file using scripts. It will have to read 3 more arguments but I have just mentioned 2 below.
Filename : testing.bat (I am creating a loop)
This is my code so far.
if exist "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\*Nursing*.csv" (
ren "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\*Nursing*.csv" names.csv
move /y "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\names.csv" \\10.10.10.10\scenarios\Nursing
)
else if exist "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\*Midwifery*.csv" (
ren "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\*Midwifery*.csv" names.csv
move /y "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\names.csv" \\10.10.10.10\scenarios\Midwifery
)
else (
echo. Not files detected!
)
timeout /t 1
testing.bat
Any help is welcome.
You have a syntax problem : the locations of the else clauses. It MUST be placed (when used) in the same line that the closing parenthesis of the if command. If you place it in the next line, the parser will take it as another command, not the continuation of the previous if
if exist .... (
....
) else if exist .... (
....
) else (
....
)
Also, while not being a problem, it is easier to place the paths you are using inside variables and use the variables instead of the literals
set "sourceFolder=E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV"
set "targetFolder=\\10.10.10.10\scenarios"
if exist "%sourceFolder%\*Nursing*.csv" (
ren "%sourceFolder%\*Nursing*.csv" names.csv
move /y "%sourceFolder%\names.csv" "%targetFolder%\Nursing"
) else if exist ""%sourceFolder%\*Midwifery*.csv" (
ren "%sourceFolder%\*Midwifery*.csv" names.csv
move /y "%sourceFolder%\names.csv" "%targetFolder%\Midwifery"
) else (
echo. Not files detected!
)
And once we are using variables to store the fixed data, we can start to use variables to hold the changing data. As the code being executed is always the same, identify the changing parts in the executed code and use for commands to iterate over the changing information and files on folders
#echo off
setlocal enableextensions disabledelayedexpansion
set "sourceFolder=E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV"
set "targetFolder=\\10.10.10.10\scenarios"
for /l %%z in (0) do (
setlocal enabledelayedexpansion
echo(!time! - Searching files ....
endlocal
set "found="
for %%a in ( Nursing Midwifery XXXX YYYY ) do (
for %%b in ("%sourceFolder%\*%%~a*.csv") do (
move /y "%%~fb" "%targetFolder%\%%~a\names.csv"
set "found=1"
)
)
if not defined found echo(.... No file detected !
timeout /t 1
echo(
)
for /l %%z defines an infinite loop (just to avoid the self call in the batch file or a goto command to a label)
for %%a will iterate over the list of "arguments". For each element in the list, the replaceable parameter %%a will hold its value and expose it to the code in the do clause, where %%~a (the value inside the replaceable parameter without quotes if present) is used to search files and determine target folder.
for %%b will search files. In this case the replaceable parameter %%b will hold a reference to the found file. This reference is later used to move the file (%%~fb is the full path to the file being referenced by %%b)
Maybe something like this. You can expand this by having a list of the file names you want to check against the server's directory. So the script then will loop at the files that matches that of your target list.
#echo off
SETLOCAL
if not exist \\deviceName\e$\directory\filename.csv (
echo filename.csv not found!
) else (
ren \\deviceName\e$\directory\filename.csv filename2.csv
move /-Y \\deviceName\e$\directory\filename2.csv \\deviceName2\e$\director\filename2.csv
if not exist \\device\e$\diretory\filename3.csv (
echo filename3.csv not found!
) else (
ren \\deviceName\e$\directory\filename3.csv filename4.csv
move /-Y \\deviceName\e$\directory\filename4.csv \\!deviceName2\e$\director\filename4.csv
)
)
ENDLOCAL
EXIT
Here is a powershell script that will cleanly handle an arbitrary number of departments and still be easy to maintain.
$DepartmentList = "Nursing","Midwifery","Ortho","Pedi"
$SourceFolder = "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV"
$DestFolder = "\\10.10.10.10\scenarios\"
ForEach($Dept in $DepartmentList)
{
if(Test-Path "E:\inetpub\wwwroot\sim_blitzv15_MSSQL\CSV\*$Dept*.csv")
{
Move-Item "$SourceFolder\*$Dept*.csv" -Destination "$DestFolder\$Dept\names.csv" -Force
$FileFound = $true
}
}
If(-not ($FileFound))
{
Write-Warning "Not files detected!"
}
If you are not using powershell yet, this is a great starter project to make that switch with.
Related
I've written a simple batch file to move .pdf files to certain folders located on a file system. Currently, the code checks to see if a folder with a company's name exists (P:\invoices\%company%). If the folder exists then the code checks to see if a subfolder called 2021 is located at P:\invoices\%company%\2021. If the 2021 folder already exists, the code moves the .pdf file to that 2021 folder.
However, if the 2021 subfolder does not exist, then the code is supposed to create a 2021 folder at P:\invoices\%company%\2021. I used the md command to do this but it creates a generic file called 2021 instead of a folder. Then the .pdf file disappears into thin air, presumably because it is moving it into a file instead of a folder.
Here is the code:
#echo off
for /r "C:\Users\me\Scan\*.pdf" %%G in (*.pdf) do set "name=%%~nG"
for /f "tokens=1-2 delims=-" %%i in ("%name%") do set "company=%%i"
if exist "P:\invoices\%company%" do (
if exist "P:\invoices\%company%\2021" do (
move /y "C:\Users\me\Scan\*.pdf" "P:\invoices\%company%\2021"
)
else do (
md "P:\invoices%\company%\2021"
move /y "C:\Users\me\Scan\*.pdf" "P:\invoices%\company%\2021"
)
)
What am I doing wrong?
#echo off
:: This ensures that the original environment is restored on termination
SETLOCAL
:: Use variable so year needs to be changed in only 1 place
set "year=2021"
:: And representing destination parent-directory
set "destparent=P:\invoices"
:: read the filenames from the tree
for /r "C:\Users\me\Scan\*.pdf" %%G in (*.pdf) do (
REM %%G has full filename, %%~nG the name part only
for /f "tokens=1 delims=-" %%i in ("%%~nG") do (
REM %%i has company name
REM Optional to auto-create company-directory begin
REM force Company directory to exist
MD "%destparent%\%%i" 2>nul >nul
REM Optional to auto-create company-directory end
REM If company directory truly exists
if exist "%destparent%\%%i\." (
rem force year subdirectory to exist
MD "%destparent%\%%i\%year%" 2>nul >nul
rem does subdirectory now exist?
if exist "%destparent%\%%i\%year%\." (
move /y "%%G" "%destparent%\%%i\%year%\"
) else (
echo "%destparent%\%%i\%year%" directory not found
)
) else (
echo "%destparent%\%%i" directory not found
)
)
)
[Untested - apply to dummy directories for verification]
OP code problems:
The for /r ... %%G will assign to name the name of the LAST file encountered, which will be the from the very last directory in the subtree that contains a file passing the name-mask *.pdf Then the value installed in name is only used to derive the company-name.
company is set up from the part before the first - in name. The part between the first and second - in name (or end of name) is assigned to %%j and never used. OP should consider the possibility that the actual company-name is hyphenated.
OP's code uses if ... DO ( (more than once). DO is illegal here and must be omitted.
OP's code uses else ... DO ( . DO is illegal here and must be omitted. The else keyword must be on the same physical line as the ) for the true code block (parenthesised sequence of statements)
The MOVE statements attempt to move ALL of the .pdf files in the selected subtree-rootdirectory to the destination, regardless of file's company-code or the fact that the selected company-code may be from the .pdf at the deepest level of the tree.
I've attempted to fix the code to do what I suspect the actual intention of the code is, being to move the .pdf files from the subtree to each file's appropriate destination\company\2021 directory, creating directories as necessary.
I will emphasise one again that this code is UNTRIED.
As a suggestion for testing, on a copy of the batch, I would replace each MD and MOVE statement with ECHO MD and ECHO MOVE respectively, and omit all of the redirection statements 2>nul and >nul (which are intended to suppress unwanted messages)
Finally, I'd insert a PAUSE line before the final goto :eof to permit the resultant proposed-list-of-changes from disappearing as I suspect that we may be dealing with a case of Heretical Clickitis.
Here's how I'd suggest you try the task:
As a batch-file:
#For /R "%UserProfile%\Scan" %%G In (*-*.pdf
) Do #For /F "Delims=-" %%i In ("%%~nG"
) Do #%SystemRoot%\System32\Robocopy.exe "%%~dpG." "P:\invoices\%%i\2021" "%%~nxG" /Mov 1>NUL
Or, as a single line entered in cmd:
For /R "%UserProfile%\Scan" %G In (*-*.pdf) Do #For /F "Delims=-" %i In ("%~nG") Do #%SystemRoot%\System32\Robocopy.exe "%~dpG." "P:\invoices\%i\2021" "%~nxG" /Mov 1>NUL
Just change the paths, %UserProfile%\Scan and P:\invoices, as needed.
[Edit /]
If you want you own code fixing, according to the comments I've already made, and to fix your two previously unmentioned typos md "P:\invoices%\company%\2021" and move /y "C:\Users\me\Scan\*.pdf" "P:\invoices%\company%\2021, which should have read md "P:\invoices\%company%\2021" and move /y "C:\Users\me\Scan\*.pdf" "P:\invoices\%company%\2021 respectively. Then this is how I'd suggest you could have fixed it:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /R "C:\Users\me\Scan" %%G In (*.pdf) Do (
Set "name=%%~nG"
SetLocal EnableDelayedExpansion
For /F "Delims=-" %%i In ("!name!") Do (
EndLocal
Set "company=%%i"
)
SetLocal EnableDelayedExpansion
If Exist "P:\invoices\!company!\" (
If Not Exist "P:\invoices\!company!\2021\" (
MD "P:\invoices\!company!\2021"
)
If Exist "P:\invoices\!company!\2021\" (
Move /Y "%%G" "P:\invoices\!company!\2021"
)
EndLocal
)
Pause
Note: As you are both creating and using variables within the same parenthesized code blocks, I have used delayed expansion to ensure that your updated variables are maintained throughout.
Please now compare my upper answer with your fixed version below it, and see why, I offered the much shorter and simpler solution initially.
These are the requirements:
Specify the wildcards to check in a variable.
For each wildcard, verify if there are files or not. Warn the user if not (just an echo).
Process the resulting files.
What I have tried (applies to only 1 wildcard):
SET wildcard=a*.txt
cd c:\somedirectory
IF EXIST "%wildcard%" (
REM PROCESS THE FILES
) ELSE (
ECHO There are no files that match that wildcard, please review.
)
This obviously only works if the wildcard is unique.
What I have tried:
SET wildcard=a*.txt b*.txt
cd c:\somedirectory
FOR %%A IN (%wildcard%) DO (
ECHO %%A
)
This prints the files that match a*.txt or b*.txt. I do not want that expansion to occur. I need the actual wildcard value to go inside the loop.
With expansion, I cannot tell the user that some his wildcards do not have files. E.g. there are files a*.txt, but no files b*.txt. I need to tell that to the user. Something like:
a*.txt: there are files.
b*.txt: there are no files, please review.
Something like (this does not work, just the idea of what I am looking for):
SET wildcard=a*.txt b*.txt c*.txt
cd c:\somedirectory
REM loop on the wildcards
FOR %%A IN (%wildcard%) DO (
REM verify if there are files for that wildcard
IF EXIST %%A (
REM loop on the files from the specific wildcard
FOR %%F IN (%%A) DO (
REM PROCESS THE FILES
)
) ELSE (
ECHO This pattern %%A has no files associated
)
)
Basically, can I prevent the expansion of values in %wildcard% inside a IF statement?
For #double-beep's comment:
your idea of multiple IF EXIST statements is exactly what I want, but I do not know how many wildcards the user will want.
SET wildcard=a*.txt b*.txt [...]
REM this would be ok
IF EXIST a*.txt ( ... )
IF EXIST b*.txt ( ... )
[...]
But how do I do that flexible, based on what the user puts in the wilcard variable? I thought of looping on the values of wildcard, but FOR does the expansion, which I do not want.
What about this piece of code, using call with parameters, which do not resolve wildcards:
#echo off
set "WildCard=a*.txt b*.txt *.vi"
call :LOOP %WildCard%
rem ...
goto :EOF
:LOOP
if "%~1"=="" goto :EOF
if exist "%~1" echo There are files that match the pattern: "%~1"
shift /0
goto :LOOP
EDIT: Updated the Code with "Stephan" Edits. I tested some dummy files and everything seems to work. Thanks for taking the time out getting this fixed and working. I can now focus on moving forward on projects instead of getting outdated game development tools working. This was for the Source Engine SDK to help get game models loaded correctly with backwards compatibility.
"sodacan.dx90.dx80.vtx" should be "sodacan.dx80.vtx".
"sodacan.dx90.sw.vtx" should be "sodacan.sw.vtx".
ORIGINAL POST:
This batch file is suppose to restore missing vtx files by copying an existing vtx file. But the vtx files require a special prefix attached to them before the extension, such as "sodacan.dx80.vtx" and "sodacan.sw.vtx".
The Problem is that the script is not working as it should. The script is ran on a folder that contains VTX files with different names. The script is suppose to create copies of a single vtx file and name them. The example below shows what you start out with and the end result.
You start out with the original, such as
sodacan.dx90.vtx (Original File)
You should end with
sodacan.dx90.vtx (Original File)
sodacan.dx80.vtx (Copy 1)
sodacan.sw.vtx (Copy 2)
But I actually get this from the code.
awning001a.dx90.vtx (Original File)
awning001a.dx90.sw.vtx (Copy 1)
awning001a.dx90.dx80.vtx (Copy 2)
These files work with there associated MDL File, such as (sodacan.mdl) but the script does not touch those files at all.
Below is the code in the batch file
#ECHO OFF
echo Initiating VTX re-construction...
set /a count=0
for /r %%F in (.) do (
Pushd %%F
for %%i in ("*.vtx") do (
for %%j in ("%%~ni") do (
echo Fixing "%%~ni.mdl".
if not exist "%%~nj.dx80%%~xi" copy "%%i" "%%~nj.dx80%%~xi" && set /a count+=1
if not exist "%%~nj.sw%%~xi" copy "%%i" "%%~nj.sw%%~xi" && set /a count+=1
)
)
popd
)
echo %count% reconstructed VTXes.
pause
Replace your for %%i loop with the following:
for %%i in ("*.vtx") do (
for %%j in ("%%~ni") do (
echo Fixing "%%~ni.mdl".
if not exist "%%~nj.dx80%%~xi" copy "%%i" "%%~nj.dx80%%~xi" && set /a count+=1
if not exist "%%~nj.sw%%~xi" copy "%%i" "%%~nj.sw%%~xi" && set /a count+=1
)
)
and at the end use:
echo %count% reconstructed VTXes.
Changes to your code:
process only the desired extension instead of processing all files and compare the extension with an if
Check if the destination file exists before copying
increment the counter only, if there was a copy
take care of the proper filenames (two dots) with another for %%j (effectively removing two "extensions")
adapted the last echo line to include the counter
(and don't forget to popd at the end of your for /R loop - there is just a limited stack for pushd and without popd you might run into that limit, generating an errormessage and exiting the script)
I'm trying to create a batch script that creates folders based on lines in a text file. I want to be able to automate the "D" function so no typing required.
#echo off
set /P D="Enter Name e.g. ABCD:"
for /F "delims=" %%a in (list.txt) DO (
FOR %%x IN (
"C:\test\%D%\%%a"
"C:\test\%D%\%%a\Folder1"
"C:\test\%D%\%%a\Folder2"
) DO (
MD "%%~x"
)
)
My List file looks like this
JACK-12345
JOHN-12345
I'm wanting to read the first 4 characters of each line and create directories in relevant folders that already exist.
So JACK-12345 will create a folder in C:\test\JACK\JACK-12345 and JOHN will create a folder C:\test\JOHN\JOHN-12345
Any help would be greatly appreciated!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "targetdir=U:\destdir"
for /F "delims=" %%a in (q35285628.txt) DO (
SET "ch4=%%a"
SET "ch4=!ch4:~0,4!"
FOR %%x IN (
"%targetdir%\!ch4!\%%a"
"%targetdir%\!ch4!\%%a\Folder1"
"%targetdir%\!ch4!\%%a\Folder2"
) DO (
ECHO(MD "%%~x"
)
)
GOTO :EOF
You would need to change the setting of targetdir to suit your circumstances.
I used a file named q35285628.txt containing your data for my testing.
The required MD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MD to MD to actually create the directories. Append 2>nul to suppress error messages (eg. when the directory already exists)
Invoke delayedexpansion to allow substringing of the metavariable %%a Assig the entire string as read to ch4 then select the first 4 characters.
!var! required within the block to access the changing value of the variable at run-time.
For the extended question (unspecified : where "maths" etc fits into the tree - additional, replacement, whatever??
Using the "meat" of the routine:
SET "ch4=%%a"
SET "ch4=!ch4:~0,4!"
SET "folder1=Folder1"
if /i "!ch4:~0,1!"=="m" SET "folder1=Maths"
if /i "!ch4:~0,1!"=="s" SET "folder1=Science"
FOR %%x IN (
"%targetdir%\!ch4!\%%a"
"%targetdir%\!ch4!\%%a\!folder1!"
"%targetdir%\!ch4!\%%a\Folder2"
) DO (
ECHO(MD "%%~x"
)
)
would replace "folder1" from the original scheme with "Maths" if the first character of the line read from the file was "m" (in either case), "Science" if it was "s" and "Folder1" otherwise.
I would like to rename files that are uploaded to another server from extension .txt to .txt_mvd and move to a different directory for archiving in a Windows batch mode. Can anyone help with what the windows batch script should be?
Thanks.
Here is the code
FOR /R C:\your_folder %%d IN (*.txt) DO (
ren %%d %%~nd.txt_mvd
)
%%d is the full file name + path
%%~nd return only the file name without the extension
Using the /R parameter, it will scan folder and subfolder
UPDATE 1
The following code should work as required.
I've added an IF that ignore the subfolders.
FOR /R E:\your_folder\ %%d IN (*.*) DO (
IF %%~dpd==E:\your_folder\ (
ren %%d %%~nd.txt_mvd
)
)
UPDATE 2
Fixed code
FOR /R E:\your_folder\ %%d IN (*.txt) DO (
IF %%~dpd==E:\your_folder\ (
ren %%d %%~nd.txt_mvd
)
)
UPDATE 3
Here is a more generalized and parametrized version of the script.
Change the starting parameter to your need (the first 4 lines of code).
This script first rename the files you choose (1st parameter) in your starting folder (3rd parameter), change the extension to the new one (2nd parameter), and then move the renamed files in the folder of your choice (4th parameter).
set Extension_of_file_you_want_to_renamne_and_move=txt
set New_extension_of_moved_files=txt_mvd
set Folder_that_contain_your_files=C:\Your_starting_folder\
set Folder_where_to_move_your_files=C:\Your_destnation_folder\
FOR /R %Folder_that_contain_your_files% %%d IN (*.%Extension_of_file_you_want_to_renamne_and_move%) DO (
IF %%~dpd==%Folder_that_contain_your_files% (
IF %%~xd==.%Extension_of_file_you_want_to_renamne_and_move% (
ren "%%~d" "%%~nd.%New_extension_of_moved_files%"
move "%%~dpnd.%New_extension_of_moved_files%" "%Folder_where_to_move_your_files%"
)
)
)
when you change the parameter DON'T add any space.
So DON'T change the parameter like that:
set Folder_that_contain_your_files = c:\myFolder <--- WRONG, WON'T WORK, there are unneeded space
instead, write the parameter WITHOUT unneeded space:
set Folder_that_contain_your_files=c:\myFolder <--- OK, THIS WILL WORK, there are no extra spaces
UPDATE 4
Fixed the code, I've added some quotation marks, without them the code wont works if folder name contained spaces.
set Extension_of_file_you_want_to_renamne_and_move=txt
set New_extension_of_moved_files=txt_mvd
set Folder_that_contain_your_files=C:\Your_starting_folder\
set Folder_where_to_move_your_files=C:\Your_destnation_folder\
FOR /R "%Folder_that_contain_your_files%" %%d IN (*.%Extension_of_file_you_want_to_renamne_and_move%) DO (
IF "%%~dpd"=="%Folder_that_contain_your_files%" (
IF %%~xd==.%Extension_of_file_you_want_to_renamne_and_move% (
ren "%%~d" "%%~nd.%New_extension_of_moved_files%"
move "%%~dpnd.%New_extension_of_moved_files%" "%Folder_where_to_move_your_files%"
)
)
)