I'm trying to use a Windows command prompt on Server 2012 R2 to run a batch file with the following command line. I want to run an SQL command (sqlcmd) and return the results to the console window.
This is what I'm currently trying, but sqlcmd keeps throwing back:
Sqlcmd: 'test': Invalid argument. Enter '-?' for help.
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -S localhost -E -i "backup.sql" -v dbname="test"`) DO (
Echo %%F
)
Note: I have also tried to run just this sqlcmd command (above) in a command prompt with no issues. It's like it does not like the FOR /F loop or something.
However if I try it without parameters/variables it works perfectly!
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -S localhost -E -i "backup.sql"`) DO (
Echo %%F
)
Does anyone know a way around getting the variables passed to my SQL query using sqlcmd, Windows CMD, as well as a FOR /F loop such as in my first example?
When a line batch code is processed it goes through multiple phases, in a specific order. The order of these phases means that in this case your equals character, = requires special attention. For a full explanation on these phases read this information.
Here's two methods, one of which was already given in the comment area.
I have formatted the command over three lines so that it's clearer, whether you do that too is optional.
Escape the equals character = with a caret ^:
For /F "Delims=" %%A In ('
sqlcmd -S localhost -E -i backup.sql -v dbname^=test
') Do Echo %%A
Or if you wish to doublequote your filename and value:
For /F "Delims=" %%A In ('
sqlcmd -S localhost -E -i "backup.sql" -v dbname^="test"
') Do Echo %%A
Surround the command in doublequotes, ":
For /F "Delims=" %%A In ('
"sqlcmd -S localhost -E -i backup.sql -v dbname=test"
') Do Echo %%A
For /F "Delims=" %%A In ('
"sqlcmd -S localhost -E -i "back up.sql" -v dbname="my test""
') Do Echo %%A
Please note as shown above, whilst it's probably good practice, Microsoft state, 'File paths that contain spaces must be enclosed in quotation marks' and 'Enclose the value in quotation marks if the value contains spaces'. They were not needed in your case and could have been omitted.
Related
Given the following:
#ECHO OFF
SetLocal EnableDelayedExpansion
cls
adb shell am start -a android.intent.action.MAIN -n com.krohne.OpticheckMobile/Droid.MainActivity -e run_bb_tests true
adb logcat -c
set condition=false
goto while
:end
echo macac
exit 0
:while
adb logcat -d -v raw | find "BBTests" | FOR /f "delims=" %%a in ('more') do (
#echo Line is %%a
if %%a==BBTestsCompleted (
echo Condition met. Exiting now ..
goto :end
)
)
goto :while
The script is not exiting through :end label, but it loops the while condition forever (the if statement is met)
The command line under :while:
adb logcat -d -v raw | find "BBTests" | FOR /f "delims=" %%a in ('more') do (
contains pipes (|), each of which initiates a new Command Prompt (cmd) instance for either side, so the for /F loop in the pipe is not executed in the hosting cmd.exe instance where the batch script runs in. Therefore, it cannot find the label :end. Furthermore, there are two contexts in which cmd.exe can run: Command Prompt context and batch file context; the instances created by a pipe are running in Command Prompt context where labels cannot be used as their usage is limited to batch file context and goto just has no effect.
For your code to work you must move the for /F loop into the hosting cmd.exe instance. This can be achieved by moving the pipes into the command line that is executed by the for /F loop (note that they need to be escaped like ^| to become hidden from the hosting cmd.exe instance):
for /F "delims=" %%a in ('adb logcat -d -v raw ^| find "BBTests" ^| more') do (
In the while class adb command contains pipes which mean that if one command failed execute other if that also fails execute other and that's the reason behind that you are not getting desired output, for this execute every adb command individually in :while class rather that using pipes
I'm trying to get a string from an url using a batch file.
String example:
e-e --ser u.g --p 3 --f 0 x,ss
I am using the command below to CURL output directly to a variable:
FOR /F %%I IN ('curl.exe -s -S %URL%') DO (SET W=%%I)
The problem is, when I echo the variable [W] after the command runs, most of the string is missing...
e-e
What is the best method to get around this issue?
By default, the FOR /F command delimits the output based on a space and tab. That is stated in the help file. To keep that from happening use the DELIMS option to tell the FOR command to not use any delimiters.
FOR /F "delims=" %%I IN ('curl.exe -s -S %URL%') DO (SET W=%%I)
im trying to create a batch file that goes thorugh each text file in a folder and looks for specific words such as "msg" "file" "size" in each line. If those words are found then it sends and me an email.
Im using SQL server to send the email, and im calling the email stored procedure from my batch file like this:
set MYDB= yourDBname
set MYUSER=youruser
set MYPASSWORD=yourpassword
set MYSERVER=yourservername
sqlcmd -S %MYSERVER% -d %MYDB% -U %MYUSER% -P %MYPASSWORD% -h -1 -s "," -W -Q "exec yourstoredprocedure"
I just need help writing the script which checks for specific words in each line in each .txt file
Just give a try for this batch file :
#echo off
Title Search String into text files
Set "ROOT=%~dp0"
set "String2Search=msg size file"
For %%a in (%String2Search%) do (
FOR /f "delims=" %%f IN ('dir /b /s "%ROOT%\*.txt"') DO (
(find /I "%%a" "%%f" >nul 2>&1) && ( Call :FoundString "%%a" "%%f" ) || ( Call :NoFound "%%a" "%%f" )
)
)
pause & exit
::*************
:FoundString
echo found %1 on file %2
goto :eof
::*************
:NoFound
echo no string like %1 found on file %2
goto :eof
::*************
Few suggestions as i cannot comment.I had done a project few years back and i had to do search files with a particular extension and read them to find particular words and do something with them.I remember few things only.I hope it helps you.
To find all txt files:
find /home/user/Downloads/etc -name '*txt'
To read a whole file and search for "msg" "file" "size":
while read -r LINE
do
grep -i "msg" | grep -i "file" | grep -i "size"
to check all in one line
Or you can do it executing one by one without "pipelining".
P.S I don't have linux installed otherwise I would have checked before posting.Sorry if not correct.
This should do the job:
#ECHO OFF
CD C:\wherever\your\.txt\files\are\at
FOR /R %%G IN ("*.txt") DO (FINDSTR /I /C:"msg" /C:"file" /C:"size" "%%G" >nul && GOTO match_found)
GOTO no_match
:match_found
ECHO Match found^!
set MYDB= yourDBname
set MYUSER=youruser
set MYPASSWORD=yourpassword
set MYSERVER=yourservername
sqlcmd -S %MYSERVER% -d %MYDB% -U %MYUSER% -P %MYPASSWORD% -h -1 -s "," -W -Q "exec yourstoredprocedure"
:no_match
ECHO No match found^!
PAUSE
If the batch file is in the same folder as the .txt files you can delete the CD line.
If the search should be case-sensitive remove the /I option.
To satisfy your question as asked, this should suffice:
#Echo Off
FindStr /IR "\<msg\> \<file\> \<size\>" "C:\Users\NT-Hero\*.txt">Nul||Exit /B
Rem Your 'match found' commands here
If you wanted to also search in sub-directories change the FindStr options to /SIR. (See FindStr /? for more options).
I'm using SQLCMD to get the count of rows in a table, but I also want to be aware if the query hits an error.
The sqlcmd I'm using looks like this:
sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
If it works, it will return:
-----------
10205
(1 rows affected)
(Note, there is a blank line above the ------- for the column name I'm not specifying.)
If I pass in a table that doesn't exist, I get the following response:
Msg 208, Level 16, State 1, Server devServer, Line 1
Invalid object name 'dbo.no_table'.
Since I have the -b flag, I can check ERRORLEVEL for a value (in this case, 1).
To store the count variable, I've been using the following line:
for /F %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^| findstr /r "[^(][0-9]"') do SET /a rec_count=%%i
After the for, %errorlevel% returns 0. Even inside the do, errorlevel is 0.
Is there any simple way to run sqlcmd, store the count if there is not an error, and print both lines if there is an error?
Commands that are executed by FOR /F are implicitly executed via a new CMD session. For example, with for /f %a in ('echo hello') do ..., the command that is executed becomes C:\Windows\system32\cmd.exe /c echo hello.
Your command is properly setting the ERRORLEVEL, but then the value is lost as soon as the child CMD session terminates and control is returned to your batch script.
So the /b option is not really doing any good for you, and can be dropped.
You can suppress the header info by adding the -h -1 option.
You can suppress the (1 rows affected) message by prefixing your command with set nocount on;
You can add the -r 1 option to cause error messages to appear on stderr instead of stdout. This will prevent FOR /F from processing any error, and the error message will appear on the screen instead.
You can clear the rec_count variable before you execute the command. Then it will remain undefined if there was an error, else it will contain the count if there was no error.
set "rec_count="
for /f %%A in (
'sqlcmd -S %server% -U %user% -P %pass% -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
One other thing you might consider is using environment variables recognized by SQLCMD for your server, username, and password. Then you won't have to use the -S, -U, or -P options. This is especially handy if your batch script runs many SQLCMD commands.
set "sqlcmdServer=YourServer"
set "sqlcmdUser=YourUserName"
set "sqlcmdPassword=YourPassword"
set "rec_count="
for /f %%A in (
'sqlcmd -h -1 -r 1 -Q "set nocount on;select count(*) from %table%"'
) do set "rec_count=%%A"
if not defined rec_count echo There was an error!
The reason errorlevel does not seem to be getting set is because the for command is executing successfully, regardless of how the code that it loops through executes. So you can only interact with the errorlevel that is set by the sqlcmd command on the same line (inside the for loop brackets).
You should be able to use || (double pipe) after the sqlcmd command. Any code after || will only run if the previous command fails. Example:
notACommand || echo test
Will return "test". While the following will output only "a command":
echo a command || echo test
I can't test it, but something like the following should work for you:
for /F "EOL=(" %%i in ('sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%" ^|^| echo fail') do (
SET rec_count=%%i
)
if "%rec_count%"=="fail" echo SQL command failed
If the output is exactly as you say, then you should not need the findstr command - just set ( open bracket as an EOL character in the for loop, so you effectively drop the "(1 rows affected)" line. You will probably want to use the variables differently, but this is just one way you can tell if the sqlcmd command has failed or not.
As for outputting the error - a bad solution is to run the same sqlcmd command again. Something like the following:
set command=sqlcmd -S %server% -U %user% -P %pass% -b -Q "select count(*) from %table%"
for /F "EOL=(" %%i in ('%command% ^|^| echo fail') do SET rec_count=%%i
if "%rec_count%"=="fail" (%command%) else echo rec_count is %rec_count%
Note that I removed the /a switch when setting the rec_count variable, because it can now be set as a word.
This works:
SET server=MyServer
SET db=MyDb
FOR /F "usebackq tokens=1" %%i IN (`sqlcmd -S %server% -d %db% -w200 -h-1 -E -Q "set nocount on; select REPORTING_DATE FROM dbo.CURRENT_REPORTING_DATE"`) DO set REPORTING_DATE=%%i
ECHO The Reporting Date is %REPORTING_DATE%
But when I try to fully qualify the path to sqlcmd...
SET sqlcmdexe="C:\Program Files\Microsoft SQL Server\100\Tools\Binn\sqlcmd.exe" SET server=MyServer SET db=MyDb
FOR /F "usebackq tokens=1" %%i IN (` %sqlcmdexe% -S %server% -d %db%
-w200 -h-1 -E -Q "set nocount on; select REPORTING_DATE FROM dbo.CURRENT_REPORTING_DATE"`) DO set REPORTING_DATE=%%i ECHO The Reporting Date is %REPORTING_DATE%
I get the error:
The system cannot find the path specified.
...presumably because of the spaces in the folder name.
How do I change the path to a tilde path (w/o spaces) or better yet, quote it so that this statement executes properly?
Note that there is a backwards tic before %sqlcmdexe% , not sure why I don't see it, at least in IE6. Yes, 6!
How do I change the path to a tilde path (w/o spaces)
As I don't have sqlcmd.exe installed, I use a different example. See for example this:
#echo off
set sqlcmdexe=C:\Program Files\Internet Explorer\Connection Wizard\icwconn2.exe
echo %sqlcmdexe%
for /f "tokens=*" %%a in ("%sqlcmdexe%") do set sqlcmdexe=%%~sa
echo %sqlcmdexe%
Run on my system, the output is:
C:\temp>envtest
C:\Program Files\Internet Explorer\Connection Wizard\icwconn2.exe
C:\PROGRA~1\INTERN~1\CONNEC~1\icwconn2.exe
But I don't know if this solves your problem.
You have to use the quotes to work with Strings... but You have never use spaces next to equal sign:
set "sqlcmdexe=c:\Program Files\Internet Explorer\Connection Wizard\icwconn2.exe"
echo.%sqlcmdexe%
Hope it helps =)