Batch move "%1" to location - batch-file

I'm writing a script that function as a shortcut, lets i wanna send the input to My Pictures
#echo off
echo drop input
pause
move "%1" "C:\Users\%username%\Pictures"
pause
The problem seems to be that the %1 / input needs to be described in some way.
cause when i drop a image it says
The system cannot find the file specified.

#echo off
rem Prepare environment
setlocal enableextensions disabledelayedexpansion
:loopParameters
rem Variable to hold file name
set "file="
rem If a file has been dropped on batch file, retrieve if from parameters
rem If no file dropped, ask for one
if "%~1"=="" (
set /p "file=Drop file here:"
) else (
set "file=%~1"
)
rem Check if there is something to do. If not, the process has ended
if not defined file goto endProcess
if not exist "%file%" goto endProcess
rem Do the work
echo move "%file%" "C:\Users\%username%\Pictures"
rem Determine if there is something more to process
if not "%~1"=="" if not "%~2"=="" ( shift & goto :loopParameters )
:endProcess
rem Wait to see output of commands
echo.
pause
rem Clean and exit
endlocal
exit /b
It will process files dropped into the batch file (without first starting batch file). If batch file is started without dropping any file on it , it will ask for one file to process.
If files are dropped into batch file, explorer generates the list of files to be processed as separate arguments to batch file. So first file will be in %1, second in %2, ... In this code, the file to be processed is retrieved from %1. Once the first file is processed, if there are more files to process, shift command is used to "shift" the argument list, so the content of %2 will be in %1, %3 will be in %2, ... That way, the next file to process will be again in %1 in each iteration.
BUT there is a limit of 8191 characters in the length of a command line. As explorer passes the full list of selected files in the same command line, if there is a lot of files selected, the final part of the list will not be handled.

You need the tilda in the command as shown below, as dropping quoted iems on it will fail if it doesn't have the tilda.
move "%~1" "C:\Users\%username%\Pictures"

Related

How to insert a line into a text file after the first line?

I play Fallout 4 VR with Mod Organizer 2 (mo2), and most mods require
*Fallout4_VR.esm
at the top of the file plugins.txt, but mo2 keeps removing it.
So I downloaded a batch file which adds that line at the top of the file on execution.
But the problem is that mo2 has this at the top:
# This file was automatically generated by Mod Organizer.
*DLCRobot.esm
*DLCworks...
etc.
This is the code in the batch file:
#echo off
cls
setlocal enabledelayedexpansion
TITLE FO4VR Launch Codes
REM Find plugins.txt
set "file=C:\Modding\MO2\profiles\Default\plugins.txt"
if not exist "%file%" (
echo ERROR - Could not find %file%
echo.
goto FAIL
) else (
findstr /b /l /i /n "*Fallout4_VR.esm" %file%
if !errorlevel! == 0 (
echo VR ESM entry already exists. Good to go.
echo.
) else (
REM needs to add
(echo *Fallout4_VR.esm) >plugins.txt.new
type %file% >>plugins.txt.new
move /y plugins.txt.new %file%
echo VR ESM entry prepended to %file%.
echo.
)
)
echo.
pause
What do I need to edit so *Fallout4_VR.esm is below the whole line with generated by Mod Organizer instead of top of the file?
The file plugins.txt should be finally:
# This file was automatically generated by Mod Organizer.
*Fallout4_VR.esm
*DLCRobot.esm
*DLCworks...
etc.
The task to add at top the line with *Fallout4_VR.esm to contents of the file plugins.txt below the comment line(s) could be done with the following code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
title FO4VR Launch Codes
rem Find plugins.txt
set "PluginsFile=C:\Modding\MO2\profiles\Default\plugins.txt"
rem Use the line below instead of the line above if the file
rem plugins.txt is always in the same directory as the batch file.
rem set "PluginsFile=%~dp0plugins.txt"
if not exist "%PluginsFile%" echo ERROR: Could not find: "%PluginsFile%"& goto EndBatch
%SystemRoot%\System32\findstr.exe /B /I /L /C:"*Fallout4_VR.esm" "%PluginsFile%" >nul
if not errorlevel 1 echo VR ESM entry already exists. Good to go.& goto EndBatch
set "LineInsert=1"
(for /F usebackq^ delims^=^ eol^= %%I in ("%PluginsFile%") do (
if defined LineInsert (
set "CommentLine=1"
for /F "eol=#" %%J in ("%%~I") do set "CommentLine="
if not defined CommentLine (
echo *Fallout4_VR.esm
set "LineInsert="
)
echo(%%I
) else echo(%%I
))>"%PluginsFile%.tmp"
if not exist "%PluginsFile%.tmp" echo ERROR: Could not create temporary file: "%PluginsFile%.tmp"& goto EndBatch
%SystemRoot%\System32\attrib.exe -r "%PluginsFile%"
move /Y "%PluginsFile%.tmp" "%PluginsFile%" >nul 2>nul
if not errorlevel 1 echo VR ESM entry added to: "%PluginsFile%"& goto EndBatch
del "%PluginsFile%.tmp"
echo ERROR: Could not update: "%PluginsFile%"
:EndBatch
echo/
if /I not "%~1" == "/N" pause
endlocal
ATTENTION: The result is only correct if
plugins.txt is not a Unicode encoded text file with encoding UTF-16
and has DOS/Windows line endings (carriage return + line-feed).
It is advisable to avoid command blocks starting with ( and ending with a matching ) because that makes it possible to do the task without usage of delayed variable expansion and therefore the batch file works also with plugins.txt stored in a directory with a path like C:\Temp\Development & Test(!) 100%. It is of course necessary to use command blocks for the for /F loop processing the lines in the text file to modify.
The outer FOR loop processes the lines in the text file with skipping empty lines and assigning each non-empty line completely to the specified loop variable I. The option usebackq instructs FOR to interpret the string in double quotes as file name of which lines to process and not as string to process. The option delims= defines an empty list of delimiters to prevent splitting the lines up on normal spaces and horizontal tabs. The option eol= defines no character as end of line character. The unusual syntax without " around the three options must be used in this special case which requires escaping the spaces and the equal signs with caret character ^ to get usebackq delims= eol= interpreted as one argument string with the three options for command FOR.
The first IF condition is true as long as the line with *Fallout4_VR.esm is not output. In this case there is first defined the environment variable CommentLine with a value whereby the value itself does not matter.
The inner for /F processes the current line as string with ignoring the line on starting with # after zero or more leading spaces/tabs. So if the current line is a comment line, the environment variable CommentLine is still defined after execution of the inner for /F while this environment variable is deleted on current line is not a comment line.
If the current line is not a comment line, there is output *Fallout4_VR.esm to insert that as line into the temporary file and the environment variable LineInsert is deleted before next is output in any case the current line.
All other lines of the text file are just output after inserting the line with *Fallout4_VR.esm detected by environment variable InsertLine no longer existing.
Everything output during execution of the outer FOR loop is written by cmd.exe into a temporary file in same directory as the text file to update which should work as long as the directory is not write-protected for the user or there is already a directory with the name of the temporary file (very unlikely) or a read-only file with that name (also very unlikely).
The read-only file attribute is removed from the file to update if it would have the read-only file attribute set.
Next the temporary file is moved over the existing file to update which can fail like on write access to file is denied because of the file is currently opened by an application which denies the shared file write access.
The batch file can be started with the option /N to avoid the user prompt with command pause at end of the batch file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
attrib /?
call /? ... for %~dp0 ... drive and path of argument 0 ... batch file path
cls /?
copy /?
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
move /?
pause /?
rem /?
set /?
setlocal /?
title /?
See also:
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
Microsoft documentation about Using command redirection operators
Single line with multiple commands using Windows batch file

How can i call resgen in a bat file if the file is edited?

I need to create a resource file using resgen.exe only if the file is edited.
I've found a way to do it, and i need to loop through all the Language available.
This is my script.
#echo on
echo ------------------------------
echo -- Starting a run of resgen --
echo ------------------------------
Set resourcesPath=%~1Resources\
Set configuration=%~2
Set platform=%~3
set landingPath=%~1bin\%configuration%\Resources\
echo %landingPath%
IF exist %landingPath% ( echo %landingPath% exists ) ELSE ( mkdir %landingPath% && echo %landingPath% created)
set obj[0].Resource="%landingPath%Strings.en-GB.resources"
set obj[0].Text="%resourcesPath%Strings.en-GB.txt"
set obj[1].Resource="%landingPath%Strings.ru-RU.resources"
set obj[1].Text="%resourcesPath%Strings.ru-RU.txt"
set obj[2].Resource="%landingPath%Strings.es-ES.resources"
set obj[2].Text="%resourcesPath%Strings.es-ES.txt"
FOR /L %%i IN (0 1 2) DO (
for %%x in ("%%obj[%%i].Text%%") do set date_of_filenameTxt=%%~tx
for %%x in ("%%obj[%%i].Resource%%") do set date_of_filenameRes=%%~tx
ECHO %date_of_filenameTxt:~0, 16%
ECHO %date_of_filenameRes:~0, 16%
IF "%date_of_filenameTxt:~0, 16%" == "%date_of_filenameRes:~0, 16%" call :same
call :notsame
:same
(ECHO "No Copy for the :" %%obj[%%i].Text%% )
call :end
:notsame
"%resourcesPath%resgen.exe" %%obj[%%i].Text%% %%obj[%%i].Resource%%
:end
)
The problem is on getting the string from the obj[], how should be the sintax?
i've found if i do as below, it works.
call echo resource = %%obj[0].Resource%%
The task could be done much easier with the following code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
echo ------------------------------
echo -- Starting a run of resgen --
echo ------------------------------
set "resourcesPath=%~1Resources\"
set "configuration=%~2"
set "platform=%~3"
set "landingPath=%~1bin\%configuration%\Resources\"
if exist "%landingPath%" echo "%landingPath%" exists.& goto ProcessFiles
mkdir "%landingPath%"
if exist "%landingPath%" echo "%landingPath%" created.& goto ProcessFiles
echo ERROR: "%landingPath%" could not be created!& goto EndBatch
:ProcessFiles
for %%I in ("%resourcesPath%Strings.*-*.txt") do (
set "RunResgen=1"
for %%J in ("%landingPath%%%~nI.resources") do if "%%~tJ" == "%%~tI" set "RunResgen="
if defined RunResgen "%resourcesPath%resgen.exe" "%%I" "%landingPath%%%~nI.resources"
)
:EndBatch
endlocal
The outer FOR loop searches in the directory Resources for non-hidden files matching the wildcard pattern Strings.*-*.txt. There could be used also the wildcard pattern Strings.*.txt or the pattern Strings.??-??.txt.
For a found text file there is first defined the environment variable RunResgen with string value 1 whereby the value does not matter.
Next is executed one more FOR processing the resource file in landing Resources directory. If that file does not exist at all, %%~tJ expands to an empty string which means the IF condition compares "" with something like "10.11.2021 19:00" and so the condition is not true. If the appropriate .resources file exists, its last modification time is compared with the last modification time of the .txt file. If the two file time stamps are equal, the environment variable RunResgen is undefined for the next IF condition because of no need to run resgen.exe for this pair of text and resources files.
The second IF condition checks the existence of the environment variable RunResgen and if this variable still exists because of .resources file does not exist at all or has not the same last modification time as the .txt file, the executable resgen.exe is executed with the two file names.
Please note that the file date/time format depends on the country setting of the used account. On my Windows machine the date/time format is dd.MM.yyyy hh:mm and for that reason the simple string comparison works with these sixteen characters plus the two surrounding quotes taken also into account on comparing the two strings.
resgen.exe must create the .resources file with last modification date/time explicitly set to last modification date/time of the .txt file or this code does not work at all.
There is usually used on Windows the archive file attribute do determine if a source file was modified since last processing it. But I suppose this is not possible here as one .txt file could be used for multiple .resources files for multiple configurations and platforms (wherever the environment variable platform is used in real batch file).
Well, the main code could be even more optimized by using just following single line:
for %%I in ("%resourcesPath%Strings.*-*.txt") do for %%J in ("%landingPath%%%~nI.resources") do if not "%%~tJ" == "%%~tI" "%resourcesPath%resgen.exe" "%%I" "%landingPath%%%~nI.resources"
The executable resgen.exe is executed on .resources file not existing at all or its last modification date/time is different to the last modification date/time of the .txt file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
for /?
goto /?
if /?
mkdir /?
set /?
setlocal /?
See also single line with multiple commands using Windows batch file for an explanation of the operator & to execute always a GOTO after an ECHO.

Loop works for first file then fails

I am a complete novice when it comes to scripting, but am attempting to write a batch script which runs a command to output a png file to a printer. The script I have works fine for one file, but when there are multiple files it does not.
Can anyone point me in the right direction please?
#echo off
REM ___Change Directory to where Label Is Stored___
pushd C:\AFP\to
REM ___Create Variable to capture filename of any png file___
for /F %%a in ('dir /b *.png') do set FileName=%%~na.png
REM ___Now we have the filename as a variable, send it to printer using Zebra SSDAL___
\\172.16.100.2\nDrive\Prime_DPD_Label_Print\ssdal.exe /p "TSC DA200" send %FileName% >> C:\AFP\Log\Label_Printing_Log.txt
REM ___Copy PNG File to Backup Folder___
XCOPY /y /q /c C:\AFP\to\*.png C:\AFP\backup\
REM ___Delete PNF File from To Folder___
DEL C:\AFP\to\*.png
When the script runs, the first file prints fine. The subsequent files then do not print, I get "File does not exist" back from the ssdal.exe command. Why would the first one work but not the subsequent prints? I would have expected the for to loop through.
#ECHO Off
SETLOCAL
REM ___Change Directory to where Label Is Stored___
pushd C:\AFP\to
REM ___Process all png files___
for /F "delims=" %%a in ('dir /b *.png') do (
REM ___Now we have the filename as "%%a", send it to printer using Zebra SSDAL___
\\172.16.100.2\nDrive\Prime_DPD_Label_Print\ssdal.exe /p "TSC DA200" send "%%a" >> C:\AFP\Log\Label_Printing_Log.txt
IF ERRORLEVEL 1 (
CALL ECHO SSDAL returned ERRORLEVEL %%errorlevel%% FOR "%%a"
) ELSE (
REM ___Move PNG File to Backup Folder___
IF EXIST "c:\afp\backup\%%a" (
ECHO MOVE "%%a" to backup skipped as file already exists IN backup
) ELSE (
MOVE "%%a" C:\AFP\backup\
)
)
REM Two-second delay
TIMEOUT /t 2 >nul 2>nul
)
POPD
GOTO :EOF
Ah! using Zebra printers. Sensible lad!
This replacement script should do what you want.
The setlocal command is used to ensure that any variation made by this batch to the cmd environment is discarded when the batch ends.
The delims= sets "no delimiters" so for/f will set %%a to the entire filename, even if it contains spaces or other delimiters. Quoting %%a ensures such filenames are kept together as a single unit, not interpreted as separate tokens.
I'm assuming that ssdal acts responsibly and returns errorlevel non-zero in the case of errors. The if errorlevel 1 means if the errorlevel is currently 1 or greater than 1 and in that case, the error message is generated. We need to call echo ... %%varname%% ... in order to display the current value of the variable, if we're not using delayed expansion (many SO articles explain this)
Otherwise, if ssdal was successful, check for the existence of the filename in the backup directory, and either move it there or report that it already exists.
Of course, there are many ways in which this could be manipulated if features I've added are not desired. I'm happy to adjust this script to comply.
timeout is a standard utility to wait for a keypress. The redirection takes care of its prompting (it will provide a countdown unless gagged).

How to fetch file time which is last created using batch script

I have one folder which contain another subfolder and that subfolder contains different extensions file.
Now I want using batch script how to extract name and time of that file in a subfolder.
I tried but failed to retrieve time of that file which is located in subfolders.
I want only this code in the batch script only.
using substitution of variable reference for /?, echo can be changed by any other command or call
command-line
for %f in (filepath\pattern) do echo "%f : %~tf"
in a script the percent sign must be double
for %%f in (filepath\pattern) do echo "%%f : %%~tf"
EDIT after comment
here an example of how to use labels to simulate function and to avoid expansion tricks, note that labels are not exactly functions they are executed in normal flow, that's why there's goto :main to skip :process and goto :eof to return.
#echo off
goto :main
:process
echo file name is: %~1 and time is %~2
goto :eof
:main
for %%x in (AppData\Local\*.*) do call :process "%%x" "%%~tx"
but with batch script command set is very limited, also should be noted that date and time output can't be formatted and are dependent of system language settings.
If powershell can be used, it's worth taking the time to learn.
Different file time properties :
$file.CreationTime
$file.CreationTimeUtc
$file.LastAccessTime
$file.LastAccessTimeUtc
$file.LastWriteTime
$file.LastWriteTimeUtc

How to get the file name and the second line of all CSV files in directory into another CSV file?

I need to analyze the results provided in a list of CSV files where I need to have the file name and its second line, this for the set of files of the result directory in a single output. I found on Stack Overflow a piece of code to get the file name and a piece of code to get the second line of a file. Frankly it is beyond my knowledge to patch them together.
This is what I have so far:
setlocal enabledelayedexpansion
#echo "filename secondline"
for /f "delims=" %%a in ('dir /b /s *.*') do (#echo %%~nxa
set filename=%%~a
echo %filename%
pause
for /f "tokens=1,* delims=:" %i% in ('findstr /n /r . %filename%') do(if %i% geq 2 if %i% leq 2 echo %j% )
rem pause
)
endlocal
How to get the file name and the second line of all CSV files in directory into another CSV file?
It is not very clear what you want. So let me add some information about what I understood.
There are some CSV files in a directory like C:\Temp which is the current directory on executing the batch file which contains for example:
C:\Temp\DataFile1.csv
first name,second name,address,country
John,Doe,"20 Baker Street, Nowhere",Fantasy Island
x,y,anywhere,anyland
C:\Temp\DataFile2.csv
first name,second name,address,country
Jane,Doe,"5 Hammer Lane, Somewhere",Happy Island
x,y,anywhere,anyland
And in same directory one more CSV file with name ExtractionResults.csv should be created containing finally for this example:
"C:\Temp\DataFile1.csv",John,Doe,"20 Baker Street, Nowhere",Fantasy Island
"C:\Temp\DataFile2.csv",Jane,Doe,"2 Hammer Lane, Somewhere",Happy Island
The file names in first column should be quoted in case of one of the CSV files have a comma in file name.
For such a task the following commented batch file could be used:
#echo off
rem Name of results file without file extension with or without path.
set "ResultsFileName=ExtractionResults"
rem Delete a perhaps already existing results file from a previous run.
del "%ResultsFileName%.csv" 2>nul
rem Delete also a perhaps already existing temporary results file from
rem a not completed previous run. A temporary file with a file extension
rem different to CSV is used for the results in case of results file is
rem created also in current directory with file extension CSV. This must
rem be done to avoid that the second line of the results file is included
rem in the results, too.
del "%ResultsFileName%.tmp" 2>nul
rem Call for each CSV file in current directory the subroutine
rem GetSecondLine with full name of the CSV file.
for %%I in (*.csv) do call :GetSecondLine "%%~fI"
rem Use command MOVE instead of RENAME to rename the file in case of results
rem file name is specified at top with an absolute or relative path as the
rem command RENAME does not allow as second parameter a file name with path.
move /Y "%ResultsFileName%.tmp" "%ResultsFileName%.csv"
rem Exit this batch file and return to parent batch file or command processor.
goto :EOF
rem This is a subroutine. It prints to the temporary results file
rem just the second line or nothing if the file contains just 1 line.
rem The execution of goto :EOF results here in exiting the subroutine.
:GetSecondLine
for /F "usebackq skip=1 delims=" %%L in ("%~1") do (
echo "%~1",%%L>>"%ResultsFileName%.tmp"
goto :EOF
)
goto :EOF
Well, the code above contains more comment lines than commands. But for an even better understanding of the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
del /?
for /?
goto /?
move /?
rem /?
And read also the Microsoft article Using command redirection operators for an explanation of >> and 2>nul.

Resources