Custom Context Menu option for duplicating selected file not working as expected - windows-7

I am trying to create a custom Context Menu option for duplicating the selected file and appending date and time string to the copied file's name.
Below is the command I have set in registry, in the HKCU > Softwares > Classes > * > Shell > Duplicate This File > Command:
cmd /s /d /c #echo off & setlocal EnableExtensions EnableDelayedExpansion & set TIME=%TIME: =0% & set DateTimeFn=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%_!TIME:~0,2!-!TIME:~3,2!-!TIME:~6,2! & copy /y %1 %1_!DateTimeFn! & pause > nul
But somehow the enabledelayedexpansion doesn't work correcty, cause when I try to use this on file test.js it duplicates it as test.js_!DateTimeFn!.
Also it doesn't work well with spaces in filenames. Can anyone guide and help fix this ?
I would prefer one-liner over creating separate batch script as far as it's possible.
Sample of registry file in which I am trying to run the command with switches and variable expansions:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate This File II]
[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate This File II\command]
#="cmd /v:on /c #echo off & set TIME=%TIME: =0% & set DateTimeFn=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%_!TIME:~0,2!-!TIME:~3,2!-!TIME:~6,2! & copy /y %1 %1_!DateTimeFn! & pause > nul"

You will need to use the argument in a FOR command and then you can use the command modifiers to get the file name separated from the extension.
cmd /Q /V:ON /E:ON /C "set TIME=%%TIME: =0%% & set DateTimeFn=%%DATE:~10,4%%-%%DATE:~4,2%%-%%DATE:~7,2%%_!TIME:~0,2!-!TIME:~3,2!-!TIME:~6,2! &FOR %%G IN ("%1") do copy "%1" "%%~nG_!DateTimeFn!%%~xG" & pause>nul"
Here is the actual registry export.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\*\shell\Time_Stamp_FileName]
[HKEY_CURRENT_USER\Software\Classes\*\shell\Time_Stamp_FileName\command]
#="cmd /Q /V:ON /E:ON /C \"set TIME=%%TIME: =0%% & set DateTimeFn=%%DATE:~10,4%%-%%DATE:~4,2%%-%%DATE:~7,2%%_!TIME:~0,2!-!TIME:~3,2!-!TIME:~6,2! &FOR %%G IN (\"%1\") do copy \"%1\" \"%%~nG_!DateTimeFn!%%~xG\" & pause>nul\""

Related

Windows Reg file seems to mess up the command syntax passed as default or special value to key

I am trying to create a .reg file which can be imported in any Windows 7-10 system which after imported, provides a context-menu option to confirm with User whether to delete logs in a specific directory and then open that same directory in Explorer.
Now the .reg file I have created apparently looks correct syntax wise and it also opens the CMD prompt, but it doesn't execute the commands due to error.
Here's that .reg file:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\Background\shell\FolderName_Logs]
#="Open folder-name's Logs"
[HKEY_CLASSES_ROOT\Directory\Background\shell\FolderName_Logs\command]
#="cmd /s /v /e /k \"set \"\"LogsDir=C:\\projects\\folder-name\\storage\\logs\"\" && if exist \"\"!LogsDir!\"\" (set /p ch=\"\"Delete Logs? \"\" && if /i !ch! equ 'y' del /f /s /q \"\"!LogsDir!\\*.log\"\") && start \"\"\"\" \"\"!LogsDir!\"\"\""
Is there any syntax trait/error that I missed here ? How to make this working ?
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Directory\Background\Shell\FolderName_Logs\command]
#="cmd /s /v /e /c set \"LogsDir=%%cd%%\" && if exist \"!LogsDir!\" (set /p ch=\"Delete Logs?\" && if /i '!ch!' equ 'y' del /f /s /q \"!LogsDir!\\*.log\") && start \"\" \"!LogsDir!\""
Note: I changed your hardcoded path to %CD% so it uses the directory you are in.

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.

SQLCMD in a 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

Resume batch script after computer restart

I have a bunch of old machines running Windows 2000 Pro and IE 5.0 which I want to upgrade to IE 6 with Silverlight. I downloaded the IE6 and Silverlight installers from Microsoft's web sites and fortunately they both have command line options to allow them to run in "silent mode".
I put the two commands in a DOS batch script and ran it, but the IE6 installer requires makes an automatic computer restart so the question is how to resume the script and run the 2nd command (install Silverlight).
My batch file is very simple right now:
ie6setup.exe /Q
silverlight.exe /q
From what I know, batch files can't resume execution after restarting the computer. Is there a way to make them do that? of is there another way to accomplish what I need.
Thank you
Based on Tim's post which, when tested, appended "two" to the batch file resulting in a failure to find the batch label "onetwo", so amended to read & write the "current" variable from a seperate text file, leaving the batch file untouched;
#echo off
call :Resume
goto %current%
goto :eof
:one
::Add script to Run key
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v %~n0 /d %~dpnx0 /f
echo two >%~dp0current.txt
echo -- Section one --
pause
shutdown -r -t 0
goto :eof
:two
echo three >%~dp0current.txt
echo -- Section two --
pause
shutdown -r -t 0
goto :eof
:three
::Remove script from Run key
reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v %~n0 /f
del %~dp0current.txt
echo -- Section three --
pause
goto :eof
:resume
if exist %~dp0current.txt (
set /p current=<%~dp0current.txt
) else (
set current=one
)
You could put the second command in a exclusive batch file, and add an entry to regedit to execute this batch file automatically upon Windows' start, making silverlight be executed after the computer restarts.
Have you heard of msconfig? On some systems the regedit PATH you are looking for is:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
But you may want to check that. If you want to make a batch file to write that key on the registry, you probably should take a look at this tutorial.
If you do the IE6 installation with the command ie6setup.exe /q /r:n then it won't reboot automatically (see this page for details). Then theoretically you could install SilverLight immediately, and then reboot afterwards; but there is a chance that the SL install will refuse due to the need of a reboot, but it won't hurt to try it...
I know its a bit old but this works amazingly:
#echo off
call :Resume
goto %current%
goto :eof
:one
echo two >>myfile.cmd
::REBOOT HERE
goto :eof
:two
echo resumed here
goto :eof
:resume
rem THIS PART SHOULD BE AT THE BOTTOM OF THE FILE
set current=one
#echo off
set "_RunOnce=HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce"
rem./ :: if no argument was passed, this line will be ignored, but if so, it will be executed here == ^> & %~1
:1st_command
ie6Setup.exe /Q
shutdown -r -t 0 | reg add "%_RunOnce%" /v "%~n0" /d "\"%~f0\" \"goto :2nd_command\"" /f & goto :eof
:2nd_command
SilverLight.exe /Q
timeout -1 | shutdown -r -t 0 | reg add "%_RunOnce%" /v "%~n0" /d "\"%~f0\" \"goto :3rd_command\"" /f & goto :eof
:3rd_command
Skype-8.92.0.401.exe /VerySilent /NoRestart /SuppressMsgBoxes /DL=1 & goto :eof
It is possible to do it without creating or manipulating readings in additional files, just writing and reading in the key and using arguments passed in the execution to control the command necessary for the relevant execution, using goto command as an argument %1
#echo off
set "_RunOnce=HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce"
rem./ if no argument was passed, below will be ignored, but if so, it will be executed here == ^> & %~1
:1st_command
mode con cols=50 lines=1 | title starting %~1
start "google" /wait "c:\program files (x86)\Google\Chrome\Application\chrome.exe" "stackoverflow.com" /new-tab
timeout -1 | shutdown -r -t 0 | reg add "%_RunOnce%" /v "%~n0" /d "\"%~f0\" \"goto :2nd_command\"" /f & goto :eof
:2nd_command
mode con cols=50 lines=1 | title starting %~1
start "google" /wait "c:\program files (x86)\Google\Chrome\Application\chrome.exe" "meta.stackexchange.com" /new-tab
timeout -1 | shutdown -r -t 0 | reg add "%_RunOnce%" /v "%~n0" /d "\"%~f0\" \"goto :3rd_command\"" /f & goto :eof
:3rd_command
mode con cols=50 lines=1 | title %~1
start "google" /wait "c:\program files (x86)\Google\Chrome\Application\chrome.exe" "www.amazon.com" /new-tab
goto :eof

Resources