SQLCMD in a for loop - for-loop

I have recently discovered that i am not able to fire the following command from a batch file:
for %%G in (%path%) do sqlcmd /S <my-server> /d <my-database> /E /i "%%G" -b
It tells me, that it could not find the command "sqlcmd". However, if I run this command directly in the command prompt (by removing one % of each pair) it works!
Why is that and how can I make it work with my batch file?
Update:
This is the following code I got in my batch file:
#echo off
set mypath=%~dp0
set mypath=%mypath%sql
for %%G in ("%mypath%") do echo %%G & sqlcmd /S sample-server /d sample-database /E /i "%%G" -b
pause

Here's your problem:
set path=%~dp0
set path="%path%sql\"
PATH is the sequence of directories Windows uses to search for executables, so when you change it, sqlcmd can no longer be found.
Simply use another variable name. Mypath seems good...

Try this:
for %%i in ("sqlcmd.exe") do "%%~$path:i" /S "my-server" /d "my-database" /E /i "%%~dp$path:i" -b
To check your path settings you can use the following code:
#echo off&setlocal
set "temppath=%path:;=";"%"
for %%i in ("%temppath%") do echo %%~i

Related

How to create a fake/dummy Windows tree from other Windows tree with Windows shell?

I have a big Windows directory and file tree. Now I need to copy this tree to another location but I do not want to copy the contents from each file. Only the structure and filenames with 0 bytes contents are needed. How could this be done with as cmd shell in Windows 10?
What I did:
xcopy /t e:\oldtreedir e:\new\oldtreedir
dir /a /b /s > mybat.bat
edit mybat.bat to:
replace \ne:\ to
\ncopy nul e:\new\
so that it is for each filename the line
copy nul e:\new\oldtreedir\file1.txt
I had to edit the mybat.bat. Could this be done by a script in the Windows command line?
PS: I found this: WIN-PRg but this program do not create a dir-tree. All files are in one dir only.
If I got your question right, robocopy should do the trick:
robocopy "E:\oldtreedir" "E:\new\oldtreedir" "*.*" /E /CREATE
No need to create an additonal batch file:
#echo off
setlocal enabledelayedexpansion
xcopy /t e:\oldtreedir e:\new\oldtreedir
for /f %%a in ('dir /b /s /a-d "e:\oldtreedir\*"') do (
set "file=%%a"
set "file=!file:E:\=E:\new\!"
break>"!file!"
)

Deleting all files and directories from desktop except .lnk

Im trying to write a script for keep clear my desktop. I want to delete all files and directories except the shortcuts.I use Windows 10. My batch code is the following:
#echo off
COLOR 0E
cd "C:/Users/DA/Desktop"
FORFILES /S /C "if #ext!=lnk del /F /Q /S"
rd /S /Q "."
pause
exit
Maybe it is a dumb error, but Im a newbie in Windows command line. Thanks in advance.
There are several issues in your code:
You must precede the command line after the /C switch of forfiles with cmd /C, because you are using internal console commands (if, del). If you omit cmd /C, forfiles tries to find a program file named if, which does not exist.
There is no comparison operator != for the if statement. You mean not equal, so you need to state if not <expression1>==<expression2> instead.
The #ext variable expands to the file extension enclosed in quotation marks, so you need to state them around lnk also. Since the "" are in the quoted command line behind forfiles /C, you need to escape them like \" in order to establish literal " characters.
You forgot to specify what to delete at the del command.
The switches /S of forfiles and also del mean to process also items in sub-directories, but I assume you do not want that, because you want to clean up your Desktop directory.
There is the rd command, so I assume you want to remove any directories from the Desktop either. However, rd /S /Q "." tries to remove the entire Desktop directory (which will fail as your batch file changes to that directory by cd). I would put the rd command into the forfiles command line as well, because there is the possibility to check whether or not the currently iterated item is a file or a directory (forfiles features the #isdir variable for that purpose).
The cd command works only if you are running the batch file from the same drive where the Desktop directory is located (unless you provide the /D switch). I would go for the pushd command, which changes to the Desktop directory temporarily, until a popd command is there.
Instead of hard-coding the location of the Desktop directory, I would use the built-in environment variable %USERPROFILE%, which points to the user profile directory of the currently logged on user, where the Desktop directory is located in.
The exit command without the /B switch does not only end the batch file, it also terminates the command interpreter instance the batch file is running in. This does not matter when you run the batch file by double-clicking, but it does matter when you execute it within command prompt.
Here is the corrected and improved code:
#echo off
title Clean Up Desktop & rem // (this is the window title, just for fun)
color 0E
pushd "%USERPROFILE%\Desktop" || exit /B 1 & rem // (the command after `||` runs if `pushd` fails, when the dir. is not found)
rem /* Here you can see how to distinguish between files and directories;
rem files are deleted with `del`, directories are removed with `rd`.
rem The upper-case `ECHO`s are there for testing purposes only;
rem remove them as soon as you actually want to delete any items: */
forfiles /C "cmd /C if #isdir==FALSE (if /I not #ext==\"lnk\" ECHO del /F /Q #relpath) else ECHO rd /S /Q #relpath"
pause
popd & rem // (this restores the previous working directory)
exit /B & rem // (this quits the batch file only; not necessary at the end of the script)
You can try something like that :
#echo off
COLOR 0E
CD /D "%userprofile%\Desktop"
Rem To delete folders
for /f "delims=" %%a in ('Dir /b /AD ^| find /v "lnk"') do echo rd /S /Q "%%a"
pause
Rem To Delete files
for /f "delims=" %%a in ('Dir /b ^| find /v "lnk"') do echo del /F /Q /S "%%a"
pause
exit
NB: When your execution is OK, just get rid of echo command
You can use the for and if commands to accomplish this:
#echo off
COLOR 0E
cd C:/Users/DA/Desktop
for /d %x in (*) do #rd /s /q "%x"
for %i in (*) do if not %i == *.lnk del "%i"
pause
Pretty simple and works great.
Make sure that %i and %x are in "".

How do I loop through files in folder to create a parameter list to pass into another script in a Windows batch file?

I have a Windows batch file that processes a bunch of files. As part of this I use the following line:
forfiles /p "%~dpn1%LogDir%" /m "%SupportLog%*" /c "cmd /c logreader.py #file > \"%~dpn1%ParsedLogDir%\#file_Logreader.txt\"
This works OK, but essentially loops through all my files (%SupportLog%*) and passes each one by one into the logreader.py script.
What I really want to do is to create a list or parameter of all these files and pass all of them at once into the Python script, such the command that should be run would resemble:
logreader.py "logfile.log" "logfile.log.1" "logfile.log.3" .....
I tried to use the set command within the forfiles command like that:
forfiles /p "%~dpn1%LogDir%" /m "%SupportLog%*" /c "cmd /c set PARAMS=%PARAMS%#file "
However, when run this and leave the ECHO ON, I see:
forfiles /p "C:\Path\log" /m "logfile.log*" /c "cmd /c set PARAMS=#file "
This is incorrect. And when I do echo %PARAMS%, I get no result.
Is there a way of achieving this?
forfiles is complicated or may even be buggy. It does not support the quotes within /c "cmd /c ...." must be replaced by hex characters 0x22, or by \".
#echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('dir /b /A-D "logfile.log.?"') do (
set _logfile=!_logfile! "%%a"
)
echo logreader.py %_logfile%
output:
logreader.py "logfile.log.1" "logfile.log.2" "logfile.log.3" "logfile.log.4" "logfile.log.5"
forfiles creates a new cmd instance per each loop iteration, so a variable PARAMS only exists as long as the containing instance.
If you want to use forfiles and work around that issue, you might do the following:
rem collect all items in a temporary file as a single line:
del /F /Q "loglist.tmp" 2> nul
forfiles /P "%~dpn1%LogDir%" /M "%SupportLog%*" /C "cmd /C echo | set /P _=\"#file \" >> \"loglist.tmp\""
rem pass over the content of temporary file as parameters:
for /F "usebackq eol=| delims=" %%L in ("loglist.tmp") do logreader.py %%L
rem clean up temporary file:
del /F /Q "loglist.tmp" 2> nul
Relying on a variable for collecting the parameters rather than a temporary file, the following could work:
rem collect all items in a variable:
set "PARAMS="
setlocal EnableDelayedExpansion
for /F "delims=" %%L in (
'forfiles /P "%~dpn1%LogDir%" /M "%SupportLog%*" /C "cmd /C echo.#file"'
) do set "PARAMS=!PARAMS!%%L "
endlocal & set "PARAMS=%PARAMS%"
rem pass over the content of variable as parameters:
if defined PARAMS logreader.py %PARAMS%
Thanks all. I eventually used a combination of the pointers listed above (and elsewhere) to come up with the following (an excerpt of the full batch file):
setlocal EnableDelayedExpansion
Set SupportLog=support.log
Set LogDir=\var\log
set PARAMS=
for %%A in ("%~dpn1%LogDir%\%SupportLog%*") do (
set PARAMS=!PARAMS! "%%A"
)
logreader.py %PARAMS% > "%~dpn1%ParsedLogDir%\%SupportLog%_Logreader.txt"
So, the a shortcut to the batch file is created in the "SendTo" folder, I can then right click the zipped log file and "SendTo" the batch, and all works as expected.
Perhaps I should switch to PowerShell for things like this going forward.

REG ADD with spaces within FORFILES command

I am trying to automate setting the App Compatibility flags for numerous EXE files we use. I can get the forfiles command to pull up all of the EXE full paths with no problem. The issue is passing that information to the REG ADD command with the space. What am I missing here? I've tried several sets of double quotes as well as single quotes but nothing is working right. What's the correct syntax for this command to work? If it can be done as shown below that's great. If it has to be done a different way, that's ok too.
Any help would be greatly appreciated.
SET Key="HKLM\SOFTWARE\Microsoft\Window NT\CurrentVersion\AppCompatFlags\Layers"
SET Command="'REG ADD' "%KEY%" /v #PATH /t "REG_SZ" /d "RUNASADMIN""
forfiles /p D:\<DIR> /S /m *.exe -c "cmd %Command%"
Try with
SET "Key=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
for /r "d:\<dir>" %%a in ("*.exe") do (
reg add "%Key%" /t REG_SZ /v "%%~fa" /d RUNASADMIN
)

Windows Batch: getting Path without Shortening

I searched now for several Hours and didnt find any fitting solution for me.
When I try to get the current Path of the Batch File, I use normaly %~dp0.
This will leads in Paths like: D:\VM\TUTORI~2\STARTS~1.BAT
However this is not an issue, if only doing File Management, but I want to use the Script to call Vagrant commands.
It happens that the Vagrant System doesnt like this shortened Paths.
As soon as the Path is short enough or when I call it from the CMD directly, it works just fine.
I'm now searching for a way to get any unshortened Path to my working Directory.
But whatever I tried so far didnt work and google only delivers me how people Shorten their Paths.
Is there a practical Solution to this Problem?
I want to set a Variable in my Script looking like this:
D:\VM\tutorialtest
EDIT:
According to the Accepted Answer the working snippet for me is the Snippet without the "-2" on the 2. For Loop. This will give me the Path no matter where the folder is.
setlocal EnableDelayedExpansion
set myPath=%~DP0
set myPath=%myPath:*\=%
set fullPath=
pushd \
for %%a in ("%myPath:\=" "%") do (
set thisDir=%%~a
for /D %%d in ("!thisDir:~0!*") do (
set fullPath=!fullPath!\%%d
cd %%d
)
)
popd
echo Full path: %~D0%fullPath%
Result:
D:\VM\tutorialtest
Try this:
#echo off
setlocal EnableDelayedExpansion
set "myPath=%~DP0"
set "myPath=%myPath:*\=%"
set "fullPath="
pushd \
for %%a in ("%myPath:\=" "%") do (
set "thisDir=%%~a"
for /D %%d in ("!thisDir:~0,-2!*") do (
set "fullPath=!fullPath!\%%d"
cd "%%d"
)
)
popd
echo Full path: %~D0%fullPath%
Post the result, please.
EDIT: Bug fixed
The problem is that names that have less than 2 characters are cutted! (my mistake).
I did some testing and it seems that for /D %%d in ("TUTORI~2*") ... also returns the full name of the folder, so thisDir variable is not required. You may modify the for %%a loop this way and get the same result:
for %%a in ("%myPath:\=" "%") do (
for /D %%d in ("%%~a*") do (
set fullPath=!fullPath!\%%d
cd %%d
)
)
Edit - Corrected the code which can work with path with or without spaces.
for /f "delims=" %i in ('dir ^| findstr /i /c:"Directory of"') do set mypath=%i
set mypath=%mypath: Directory of =%
Above codes will work if you type them directly in command console, if you want to use it in batch file use it as below.
for /f "delims=" %%i in ('dir ^| findstr /i /c:"Directory of"') do set mypath=%%i
set mypath=%mypath: Directory of =%
I believe you are in need of getting the current working directory(something like pwd in Unix). 'dir' command usually returns the current path details along with variuos other details. We just pick the line with the directory name (line with the tag "Directory of") and then in the second line we remove the tag "Directory of" (replacing it with none).
Refer the below link for more string manipulation techniques.
http://www.dostips.com/DtTipsStringManipulation.php
Sample output - typed on command console
C:\test\new folder>for /f "delims=" %i in ('dir ^| findstr /i /c:"Directory of"') do set mypath=%i
C:\test\new folder>set mypath= Directory of C:\test\new folder
C:\test\new folder>set mypath=%mypath: Directory of =%
C:\test\new folder>echo.%mypath%
Did you try :
set $path=%cd%
echo %$path%
If this behaviour occurs when you open a cmd window, then type echo %comspec% at the cmd prompt and see what it returns: if it has command.com as part of it then it has been altered.
Another possibility is that the shortcut you are using to open a cmd window has command.com in the properties to launch it.
If you are using a shortcut then try to open a cmd prompt from the Win+R hotkey and type cmd and enter. See if this behaviour has changed but also check the first point above once more.

Resources