I am trying to run a command in a batch script to parse to the fourth word of a line.
This command works fine on the command line but gives an error when run inside a script. The error states :
Skip was not expected at this time
db2cmd -i -c FOR /F "usebackq skip=3 tokens=4" %%G IN ("aliasname.txt") DO DB2 UNCATALOG SYSTEM DATABASE %%G
Could you please check what might I be doing wrong here?
Two different options, achieve the same result, depends on your style.
omit the explicit db2cmd -i -c prefix for any Db2 CLP action and auto run the whole script under db2cmd . This has the advantage that it will run either in a CMD.EXE or DB2CMD.EXE window without change. In this case you do not need special quoting or escaping. The batchfile would look like this (adjust the path of db2cmd to suit your environment).
set db2cmd="C:\Program Files\IBM\SQLLIB\BIN\db2cmd.exe"
#if "%DB2CLP%"=="" %db2cmd% /w /c /i "%0" %* && #goto :EOF
FOR /F "usebackq skip=3 tokens=4" %%G IN ("aliasname.txt") DO DB2 UNCATALOG DATABASE %%G
If you prefer explicit db2cmd -w -c prefix on Db2 CLP commands, then you must escape the double-quotes as mentioned by Mark Barinstein's answer, although the %%G is required then inside the script:
db2cmd -i -c FOR /F \"usebackq skip=3 tokens=4\" %%G IN ("aliasname.txt") DO DB2 UNCATALOG DATABASE %%G
-
Additionally, you may need to fix the syntax of the Db2 CLP command e.g. db2 uncatalog system odbc data source or alternatively db2 uncatalog database depending on what you wish to uncatalog.
You have to use %G variable reference if you run command from the command line, not %%G as you use in batch files.
Double quotes must be escaped.
Try this:
db2cmd -i -c FOR /F \"usebackq skip=3 tokens=4\" %G IN (\"aliasname.txt\") DO DB2 UNCATALOG SYSTEM DATABASE %G
BTW,
There is no UNCATALOG SYSTEM DATABASE DB2 command.
There is UNCATALOG DATABASE.
Related
The following question has helped me solving the problem of executing multiple SQL Scripts located in file. Run all SQL files in a directory
However, I did not get how to redirect the output into a separate log file. Someone suggested the following script but since I don't understand it, it did not work and I can't find out the error.
for %f in (*.sql) do sqlcmd /S <servername> /d <dbname> /E /i "%f" >> sql.log 2>&1)
If you need the output into one common file then you should use the #Abhishek 's answer.
If you need the output into a separate log file for an each input sql file
then you can use -o parameter of sqlcmd command. Your bat file could look like this:
for %%G in (*.sql) do sqlcmd /S <servername> /d <dbname> -E -i"%%G" -o C:\logs\%%G.log
pause
In this case for
1.sql
2.sql
you will get:
1.sql.log
2.sql.log
You are seeking Command Redirection.
As per your example -
for %f in (*.sql) do sqlcmd /S <servername> /d <dbname> /E /i "%f" >> sql.log 2>&1
once the execution of the sql script is done the output will be redirected to and appends the command output to the end of file (here sql.log) without deleting the information that is already in the file (>>) and redirects STDERR (2) into STDOUT handle(1) - 2>&1
More information here and here.
I have been banging my head with this small script to search a delete a file from the remote host. However, I have been able to write to seperate scripts, both to delete and to find a file.
However, now I am trying to merge both and I am unable to use the for loop in the same line as the line which searches the file.
Psexec #IPlist.txt -u ad -p P#$$vv0rCL cmd /c (^WHERE /r D:\ %file%>res.txt
the above line helps to search the file, and below does the deletion part.
del /f /A:H /S /Q "D:\1\e.txt"
Now, since I want to delete all the files, found and stored in rex.txt, I need to run a for loop on this file.
Here is what I am trying to do
Psexec #IPlist.txt -u ad -p P#$$vv0rCL cmd /c (^WHERE /r D:\ %file%>res.txt ^& FOR /f "delims=" %%X IN (res.txt) DO ( del /f /A:H /S /Q "D:\1\e.txt")
but this gives error cmd exit with error code 1, and if I take for loop on next line, then the code doesn't work on remote pc.
Can some one guide please?
escape the ) in (res.txt) as ^)
The Windows command line interpreter features a FOR command, which is able to parse the output of a given command and execute the loop for each line of the output, e.g.:
FOR /F %%i IN ('DIR .') DO echo %i # Outputs each file name
The command (DIR .) is executed in a child command line via cmd /C <command> <command-arguments>, however, the /D parameter is not specified ... this leads to weird behavior if the user has a AutoRun command with output (e.g. echo, or cls).
Is there a way to force FOR to execute the command via cmd /C /D <command> <command-arguments>?
You have run across one of the many design flaws of cmd.exe, and this one has bothered me for quite some time. I'm pretty sure there is no way to suppress AutoRun when FOR /F executes a command.
What makes this especially irritating is that pipes also use CMD /C (one for each side of the pipe), but the designers of the pipe were smart enough to incorporate both the /D and /S options. It is really a shame the designers of FOR /F couldn't have done the same.
I believe your only recourse One option is to be defensive within your AutoRun command definition. I suggest putting all the AutoRun commands within a batch script that has something like the following at the top:
#echo off
if defined AutoRunComplete exit /b
set AutoRunComplete=1
REM Put your AutoRun commands below...
But if you cannot control the AutoRun commands, then I think you are out of luck. Aacini's idea of using a temporary file to get around the problem is an effective and simple solution.
A very simple solution for your problem is use a file in the for /F command instead of a command. This way, we just emulate the internal operation of for /F over a command, but executing each step explicitly: 1. Execute the command and store its output in a temporary text file. 2. Process all lines in the temporary file. 3. Delete the file.
DIR . > TempFile.txt
FOR /F %%i IN (TempFile.txt) DO echo %%i
DEL TempFile.txt
When you have many FOR /F blocks for parsing program output, then it could be useful to add a cmd.exe wrapper.
This wrapper can be installed with
set "comspec=C:\somewhere\cmdWrapper.exe"
FOR /F %%i IN ('DIR .') DO echo %%i
The wrapper itself has to start the original cmd.exe with /D /C.
But the behaviour of the comspec variable itself is a bit strange.
I have a batch file that runs multiple SQLCMD commands which run queries supplied by external SQL script files. The scripts themselves are fairly trivial, but I'm bugged by all the file dependencies required to run the batch. I've been googling for ways to link all these files together without luck.
Are there any techniques I can apply to encapsulate the batch script and SQL scripts within a single file, such that I could move the resulting file to other machines without dragging the individual sql files along? For the sake of organization/readability/information hiding, I would really prefer to avoid embedding the sql directly in the batch file.
Consider using 7-Zip. It is free and here
You could encapsulate all your BAT files and SQL commands into a zip like this:
C:\> 7za a -t7z archive.7z *.BAT *.SQL
Then you can extract like this:
C:\> 7z e archive.7z
Alternatively you could make a self-extracting executable with it - which has the benefit you don't need any tools to extract it when you arrive at another server, but you may not be able to Email that. By the way, if you change the command to the following, Windows can read the archive itself natively so you don't need to install extraction software wherever you go with the file:
C:\> 7za a -tzip archive.zip *.BAT *.SQL
Or you could use the Microsoft CAB tool that will be present everywhere documentation.
That would look something like this if you wanted to gather *.BAT and *.CMD into a "cabinet" called BATplusSQL.cab:
dir /b *.BAT *.CMD >files.txt
makecab /d "CabinetName1=BATplusSQL.cab" /f files.txt
del /q /f files.txt
Here is an example of what I mean.
Create a text file with one SQL query per line similar to this:
My Queries
Select * from table1 where something = somethingelse
Select * from table2
delete from table3
update table1 set something=nothing
Make sure the first line is not a query. It can be anything else. Tweak the settings in %sql% as necessary.
Run the following batch file:
#echo off
setlocal
set "sql=sqlcmd -S MySERVER -E -q "
set cnt=1
for /f "tokens=* skip=%cnt%" %%a in (sqlQueries.txt) do (
echo %sql% "%%a"
set /a cnt+=1
)
Remove the echo to run the queries.
I am using sql server 2008 , I am developing script that get all .sql file of given path ( also serch in subfolder recursively). Thanks in advance.
You could use a batch file like this. Call it ashwin.bat (or whatever you like) and it will look for all the files in C:\tmp\so\ashwin that have a .sql extension and then invokes sqlcmd against all of those files against a named instance database of localhost\localsqla and runs them in the master database.
#echo off
For /R "C:\tmp\so\ashwin\" %%i in (*.sql) DO CALL sqlcmd.exe -E -S localhost\localSQLA -d master -i %%i
A litle enhancement for logging purposes:
#echo off
For /R "C:\Deploy\SQL" %%i in (*.sql) DO CALL echo %%i && sqlcmd.exe -E -S DB_IP -d DATABASE -i %%i -j