so ive been searching for the solution to this problem for awhile now, everywhere i look everyone just says "set the compsec to point to cmd"...which is super helpful cause no one actually even says how to do that.
but when i open cmd, and type "Set" and hit ENTER, it shows ComSpec=C:\Windows\system32\cmd.exe
I checked there and sure enough, cmd.exe is in there, it works just fine. But for/f still closes before performing any operation.
How do I fix this?
#echo off
for /f "tokens=2*" %%a in ('dir /b /s findstr "Find Me Testing"') do set "AppPath=%%~b"
set "AppPath=%AppPath%"
echo %AppPath%
for /f "tokens=2*" %%a in ('dir /b /s /a-d ^| findstr "Find Me Testing"') do set "AppPath=%%~b"
set "AppPath=%AppPath%"
echo %AppPath%
pause
for /f "usebackq" %a in ('dir /b /s /a-d ^| findstr "To Be Deleted.me"') do set fileLocation=%~pa
echo %fileLocation%
pause
pause
stop
pause
wait 50
As you can see I've been testing various methods of doing what I want.
I lay good odds that your problem is with the cmd.exe autorun feature.
If you open a command session and enter cmd /?, then at about the 5th paragraph you will see the following:
If /D was NOT specified on the command line, then when CMD.EXE starts, it
looks for the following REG_SZ/REG_EXPAND_SZ registry variables, and if
either or both are present, they are executed first.
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
and/or
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
I'd be willing to bet that one of those two registry settings is set to a command or script that is causing your problem. Edit your registry and remove those settings, and your problem should go away.
You can see a similar story about a user having trouble with FOR /F at https://blogs.msdn.microsoft.com/oldnewthing/20071121-00/?p=24433.
The FOR /F command executes your commands within your IN('....') clause via a new cmd.exe process, and that process will always run any autorun setting that may be present. Unfortunately it is impossible to disable this FOR /F "feature" - I think this is a horrible design flaw.
Windows pipes also use child cmd.exe processes - one for each side of the pipe. But the pipe instantiation of cmd.exe includes the /D option, so autorun is disabled. You can see this by running the following command from the command line:
echo %^cmdcmdline% | findstr "^"
On my machine it produces the following:
C:\WINDOWS\system32\cmd.exe /S /D /c" echo %cmdcmdline% "
Now do the equivalent with FOR /F (on a healthy machine)
for /f "delims=" %a in ('echo %^cmdcmdline%') do #echo %a
My machine produces:
C:\WINDOWS\system32\cmd.exe /c echo %cmdcmdline%
No /D option :(
Related
I have a folder with some subfolders, like:
C:\Users\User\Desktop\ABC\V1_0_1_win64
C:\Users\User\Desktop\ABC\V1_1_1_win64
C:\Users\User\Desktop\ABC\V1_1_4_win64
C:\Users\User\Desktop\ABC\V1_2_1_win64
C:\Users\User\Desktop\ABC\V1_3_0_win64
I want to open with the .bat file the latest revision, here: V1_3_0_win64.
How can I open always the latest revision automatically with the .bat file?
Here's an example using the existing comments as a base.
This version additionally uses findstr to ensure that the dir command wildcards actually match single digits.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "BaseDir=%UserProfile%\Desktop\ABC"
PushD "%BaseDir%" 2>NUL&&(Set "LatestVer=")||Exit /B
For /F Delims^=^ EOL^= %%A In (
'"Dir /B/AD-L/O-N "V?_?_?_win64" 2>NUL|"%__AppDir__%FindStr.exe" /I "V[0-9]_[0-9]_[0-9]_win64""'
)Do If Not Defined LatestVer Set "LatestVer=%%A"&GoTo OpenIt
Echo Latest version directory not found!&"%__AppDir__%Timeout.exe" /T 3 /NoBreak>NUL&Exit /B
:OpenIt
Start "" "%SystemRoot%\Explorer.exe" "%LatestVer%"
The example above assumes by "open" you actually meant in Windows Explorer, so I have included that as a fully qualified command, despite Start "" "%LatestVer%" also being valid. You may need to adjust that command, as well as the path between the = and closing " on line 3, (to suit your chosen base directory source location).
To read the usage information for the commands used, open a Command Prompt window and enter the command name followed by its help option. e.g.
echo /?, setlocal /?, set /?, pushd /?, exit /?, for /?, dir /?, findstr /?, if /?, goto /?, timeout /? and start /?.
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 "".
I'm working on a - I thought - simple script, which can install multiple programs.
So let's see, this is my directory with the mandatory files.
C:\variables.ini
C:\programs.txt
C:\update.cmd
C:\scan.cmd
C:\storage\ *.exe
Example for *.exe is "scribus-1.4.4-windows-x64.exe"
variables.ini contains
prog=C:\programs.txt
programs.txt contains
scribus-1.4.4-windows-x64.exe
scan.cmd contains
dir C:\storage /b /a-d > programs.txt
Now the problem: update.cmd
#ECHO OFF & SETLOCAL
REM Read variables
for /f %%i in (C:\variables.ini) do set %%i
cd C:\storage\
for /f %%i in %prog% do %%i /Q /S
ping localhost -n 5 > nul
del %%i
ping localhost -n 5 >nul
exit
How works the update.cmd?
I've a main .cmd from there I call multiple .cmd files which do several things. As you see, I run in the first place the scan.cmd. It scans the c:\storage\ dir and write the content into c:\programs.txt. In the variables.ini is the programs.txt file as %prog% variable embedded. Now I run update.cmd and it takes the first variable program from the programs.txt, in this case scribus, and start the install with /silent and /quiet flag (some programms use /s and others /q, but not both, maybe a possible bug, but I had no better idea). After the install it waits for 5 seconds and remove the .exe file. If there are other executables, then the script start again til the storage dir is empty.
I hope you understand me... I tried some other ways, but I failed.
So I tried it without the variables file and executed the scan command inside the update.cmd
#ECHO & SETLOCAL
cd C:\storage\
for /F %%i in ('dir C:\storage /b /a-d') do set %%i
%%i /Q /S
ping localhost -n 5 >nul
pause
There I get some errors, that scribus is no environment variable. I don't know why it should be anyone? I tried google and read many tutorials and threads about for-loops, but not one person executed a setup file from a variable.
Does anyone know a way how I can fix this?
Many thanks in advance!!
Noting that your paths are horrible: don't install things into the root of the system drive.
As is cmd.exe: PowerShell is the future and vastly more powerful. And using ping for a delay (it sends the next ping as soon as the previous received: so not a good timing mechanism).
But I think all you need to do it launch executables is
start /wait command
which will not return until command has finished.
You also seem to be trying to run multiple commands in a for loop in cmd, this is possible:
for /F %%i in ('dir C:\storage /b /a-d') do set %%i && %%i /Q /S
using && to separate the commands (it is not clear why you have set %%i: it will just list variables with the name, you're not setting a value).
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.
I have directory structure:
DIR
|-UNINSTALL.BAT
|-component_name
|-source
|-setup.exe
|-uninst.bat
|-another_component_name
|-source
|-setup.exe
|-uninst.bat
|-yet_another_component_name
|-source
|-setup.exe
|-uninst.bat
and so on...
In every directory like "component_name" I have setup.exe file which installs current component to the palette component in Delphi.
uninst.bat contains only this string:
"setup.exe" /uninstall
So I need to write UNINSTALL_ALL.bat in DIR that would run the uninst.bat in all component directories.
Thank you in advance.
you could do it with this line:
for /f %%a in ('dir /b /s uninst.bat') do call %%a
note that the '%%' is necessary for batch files. if you are testing this on the command line, only use one '%'
That is kind of akward in a batch file. Though you could probably do it with the foreach statement. I would suggest though that you have a look at Powershell which will definitely give you the power to do this simply and a whole lot more if you want it.
You want to use the "for" construct. Something like this:
for %%i in (component_name another_component_name yet_another_component_name) do %%i\uninst.bat
The double-escaping (%%) is necessary if you put the "for" loop in a batch file. If you are just typing it out in a command prompt, only use 1 %.
Also, you may be able to use a wildcard to match against the directory names, if they follow some convention. Open up a command prompt and run "for /?" to see everything it can do...I believe there is a /d option to match against directories. That would look something like:
for /D %%d in (component_*) do %%d\uninst.bat
(obviously, adjust the wildcard to match your component directories.)
This should work:
FOR /F %%a IN ('dir /b /s uninst.bat') DO START /B %%a
if you want them to wait each other, use this:
FOR /F %%a IN ('dir /b /s uninst.bat') DO START /B /WAIT %%a
The way you describe your problem, you have only one level of sub-directories and you always call the same batch, from the root. Therefore:
Uninstall_all.cmd
#echo off
for /F "delims=" %%d in ('dir /b /ad') do cd "%%d"& start /b /w ..\uninstall.bat& cd ..
Should do the trick.