Use Dos commands to copy file and preserve date in file name - batch-file

I'm having trouble trying to copy and rename a file using only dos commands. I have a file of the format myfile20130218 and want to copy and rename it to some_other_file_20130218.
I know I can use copy source dest but I'm having trouble with how to isolate the date and preserve it. I cannot guarantee that he date will be today's date so that is ruled out, the source file will always be the same name.
I can run either a series of commands or a batch script, but thing that that I am currently having trouble with, is after I find a match that I need to copy, using myfile????????, how can I now get those file names to pull the dates off them?
EDIT: for clarification I will be looking at files in a known directory, as above, I will know the format of the file name, and will only be checking a specific directory for it. The process that checks the directory is a ConnectDirect file watcher, so when a file is found matching myfile20130218 I can fire off some commands, but don't know how to check the directory and get the name of the file present.

Something like this should work:
%oldname:~-8% extracts the last 8 characters from %oldname% which are then appended to the new filename.
Update: If you can identify the file with an external program and then call the batch script with the file name
copyfile.cmd C:\path\to\myfile20130218
you could do something like this:
set oldname=%~nx1
set newname=%~dp1some_other_file_%oldname:~-8%
copy "%~f1" "%newname%"
Update 2: If you know folder and the format you could call the script with the folder
copyfile.cmd C:\folder
and do something like this:
#echo off
setlocal EnableDelayedExpansion
for /f %%f in (
'dir /b "%~f1" ^| findstr /r "myfile[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$"'
) do (
set oldname=%~f1\%%f
set newname=%~f1\my_other_name_!oldname:~-8!
copy "!oldname!" "!newname!"
)
endlocal
Edit: Script breakdown.
setlocal EnableDelayedExpansion enables variable expansion inside loops and conditionals.
for /f %%f in ('...') executes the command between the single quotes and then loops over the output of that command.
dir /b "%~f1" lists the content of the given directory (%~f1 expands to the full path of the first argument passed to the script) in simple mode (no header, no summary).
findstr /r "myfile[0-9]...[0-9]$" filters the input for strings that end with the substring "myfile" followed by 8 digits. The circumflex before the pipe (^|) escapes the pipe, because otherwise it would take precedence over the for command, which would effectively split the for command in half, resulting in an invalid command-line.
set oldname=%~f1\%%f assign the full path to a matching file to the variable oldname.
set newname=%~f1\my_other_name_!oldname:~-8! assign the full path to the new filename ("my_other_name_" followed by the trailing 8 digits from oldname) to the variable newname.
copy "!oldname!" "!newname!" I don't need to explain this, do I?

Related

Renaming multiple files in a for loop with user input Windows batchfile

I want to create a program that can loop through multiple pdf files and have the user rename each file a unique name like so:
234324.pdf to Batch150.pdf
32154687.pdf to AdvancedPayment.pdf
and so on...
Here is my code:
setlocal EnableDelayedExpansion
echo rename pdf files
FOR %%F IN (*.pdf) DO (
set /p x=Enter:
move %%F !x!
)
endlocal
This seems to work for the first file and then when I try to rename the second one it says: The syntax of the command is incorrect..
I have tried using the rename command and haven't had much luck with it.
FOR %%F IN (*.pdf) DO (
SET "x=%%F"
set /p "x=%%F Enter: "
IF /i "!x!.pdf" neq "%%F" ren "%%F" "!x!.pdf"
)
Your code worked fine for me. Since you don't indicate what the "to" and "from" names you used were, we're reduced to guessing.
I developed the above code to perform the rename in the manner you originated. Note that it works as I expect. Using ren the "to" filename must be a filename within the directory where the "from" file resides [ie. it simply renames the file]. If you use "move" then the file can be moved to another directory if you specify that in the "to" name.
The first fix is purely cosmetic. By enclosing the variablename and prompt in the set /p in quotes, you can include a terminal space in the prompt (which I prefer), and including the %%F in the prompt shows you which file is about to be renamed.
The next fix is to quote the arguments to the ren or move. This ensures the syntax remains properly constructed in the case of eithr "to" or "from" name containing a space.
The next is to initialise x with the "from" filename. It's enclosed in quotes so any invisible trailing spaces are not included in the value assigned to x. Note that set /p does not alter the variable if Enter alone is keyed, so setting x ensures that if a file is not to be renamed, all you need do is press Enter
The next is to detect whether the "to" and "from" names are equal. ren will generate an error report if you attempt to rename a file to itself; equally, you can't move a file to itself. Hence, /i=ignore case, and only attempt the operation if the names are different.
Finally, add the .pdf to each usage of !x! in order that you don't need to key it in. Naturally, you could omit this change if you want to alter extensions or you could put .pdf into another variable and use that variable in place of the constant .pdf so that the extension being selected can be easily varied by being changed in one plaace rather than using a mass-edit. You could even use a set /p to assign the extension being processed dynamically at the start of the routine.
Note that if you rename say one.pdf to yellow.pdf then this construct is very likely to propose yellow.pdf for a rename later on. This is because the next-filename logic locates the next filename currently in the directory,then processes the loop, then locates the next filename currently in the directory, and so on.
You would need
For /f "delims=" %%F in ('dir /b/a-d "*.pdf" ') do (
to ensure that each filename is only presented once. This mechanism performs a directory scan of filenames-only in basic form, and stores the list in memory, then processes the list item-by-item and since that list is created and then processed, any subsequent alterations to the directory do not affect the list.

About Copying Files

I want to copy some files to same destination.
Files which will be copied are listed in a text file.
So, how to read file list from text file and copy via using cmd
command?
I tried this command:
for /f "delims=" %%L in (foo.txt) do copy "%%L" new_folder
Similar question was asked in this website, I know that. When I use this command, files will be copied; but folders which include these files won't be copied.
I want to copy files with their directories.
What should I do? (Sorry for my awful English.)
You use %%L in a batchfile and %L when typing interactivly.
Your command, depending on other factors, should have a path specified for new_folder.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
.
--
Ok ,I have solved my problem via searching another cmd command:
for /f "delims=" %%i in (filelist.txt) do echo F|xcopy "-Source root folder-\%%i" "-Destination folder-\%%i" /i /z /y
In spite of the fact that I have solved my problem myself, thanks guys for your helps.
I appreciate it too much!

batch file to swap out info between two files

I need help with a batch file to do the (I suppose simple) task of reading info from a master file between two "tags" and overwriting current info in other file with the info from this master file.
Here is my situation as a simple example:
I have a file called "template.htmltplt" that is my master file if you will. Then I have a bunch of other ".html" files.
I would like the batch file to:
Go through all the html files
Delete all the lines between <!--Stuff-Start--> and <!--Stuff-End-->
Copy the content between the <!--Stuff-Start--> and <!--Stuff-End--> tags in the template.htmltplt into their correct place in the other html files.
Is this even possible and if so how?!
I have NO bat script knowledge so well commented code would be awesome!
Thanks in advance for those willing to help!
Regards,
Reinhardt
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "startstring=<!--Stuff-Start-->"
SET "endstring=<!--Stuff-End-->"
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
(
SET "block="
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r "^" q23715314.txt') DO (
IF "%%b"=="%endstring%" SET "block="
IF DEFINED block ECHO(%%b
IF "%%b"=="%startstring%" SET block=Y
)
)>"%tempfile%r"
FOR /f "delims=" %%t IN ('dir /b /a-d %sourcedir%\*.html') DO (
SET "block="
FOR /f "tokens=1*delims=:" %%a IN ('findstr /n /r "^" "%sourcedir%\%%t"') DO (
IF "%%b"=="%endstring%" SET "block="
IF NOT DEFINED block ECHO(%%b
IF "%%b"=="%startstring%" SET block=Y&TYPE "%tempfile%r"
)
)>"%destdir%\%%~nt.html"
del "%tempfile%*"
GOTO :EOF
Not hard.
I used a file named q23715314.txt containing this data for my testing:
drop <this> line
<!--Stuff-Start-->
Insert this
and this
and even <this> line after an empty line
<!--Stuff-End-->
omit this
leave this out
And test .html file:
leave <this> line
empty line retained
<!--Stuff-Start-->
Replace this
replace this too
and substitute for <this> line
<!--Stuff-End-->
keep this
retain this too
resultant new .html file:
leave <this> line
empty line retained
<!--Stuff-Start-->
Insert this
and this
and even <this> line after an empty line
<!--Stuff-End-->
keep this
retain this too
Naturally, you'd need to set your own file and directory names, and I'd advise strongly against trying to use the same directory for the source and destination. That won't work at all. And any .html source line that starts with one or more colons will have those colons stripped-out - not that many .html lines start with colons, but it needs to be said...
How it works - block by block.
The first part would seem obvious. The directories involved are defined and the target strings, too.
Next there's a create-a-tempfile routine. Simply generate a random filename and see whether there is an existing matching filename in directory %temp%. Personally, I set up temp to be c:\temp but the code is designed to use the default. So, if the random-number generator chooses 18749 then the code looks for any file 18749... in the temporary directory. If such a file exists, then choose another random number. If it doesn't create a file named 18749a in the temporary directory. This is simply a placeholder.
Next step is to extract the required lines to a temporary file. the (block of code)>filename syntax directs any data echoed to a new file in filename - which should contain the full filename of a valid file in the temporay directory; for example c:\temp\18749r.
The code within the block first sets block to empty, then reads the file q23715314.txt line-by-line, numbering each line by prefixing it with number:. This ensures that empty lines are processed as 13:, otherwise they'd be skipped. The q23715314.txt isn't significant - it can be any file containing the required template data. I simply use qSOquestionnumber.extension in order that I can keep the data in files related to the batch file I write (called qSOquestionnumber.bat) - so the many questions using file1 and file2 can be easily individually retrieved in the case of a problem. The temporary file could be any valid filename you like, if you want to have a fixed filename. Note however that filenames containing spaces and some other symbols will need to be "quoted".
Since each line is processed by the for as it it was number:linefromfile then using tokens=1*delims=: will assign the number to %%a and linefromfile to %%b.
The block processing simply matches the line that was read from the file to the start/end string defined. block was originally "set" to empty, so it is undefined. When the startstring is matched, block is assigned a value. I used Y, but any value will do.
When the for reads the next string from the file, it finds that block is now defined, so it echoes %%b to the file c:\temp\18749r. This continues until endstring is found, when block is "set" to empty again; hence it is undefined and there is no more echoing to c:\temp\18749r.
The inner for of the second block is similar, but reversed. It reproduces each line from the file selected in the outer loop until the startstring is found, then types the contents of the tempfile and waits for the endstring when it clears blockand hence turns onthe echoing again.
The outer loop simply reads dir /b /a-d for the source directory - a directory list of simply the filenames. The "delims=" assigns the entire line to %%t and hence the outer loop is for...%%t...do (innerblock)>"%destdir%\%%~nt.html" which redirects the data echoed by the inner loop to the file with the name part of %%t (%%~nt) with the destination directory specified and the extension .html
Finally, the tempfiles are deleted.
You can't do that with a batch file. Use visual basic or pearl for something like that. Closest a batch file could do to something like that is have the output from one file be used as the input for another file but that's as specific wait can get.
Lottopix.has > prevwinum.cgi

Bat file find folder of file

So my many attempts to search for a solution have resulted in a million ways to find the folder of the bat file being executed, however what I am looking to do is find the folder for the filename being passed to the bat file.
Example:
C:\Temp\runthis.bat "C:\Blah\Ah Argh\rage.txt"
I want to get a string within that bat file that is simply "C:\Blah\Ah Argh\", alternatively I would also be able to work with getting a string of "rage.txt"
Editing to explain why: Looking to check for the filename within another txt file which is the directory listing of a ftp server to verify that a file successfully uploaded to it. Then if successful I need to move the file to a subfolder of the original folder \uploaded\ but we have many of these folders setup so I can't hard code it.
Thanks
#echo off
The file path is %~dp1
The file name is %~nx1
The parameter modifiers are the same as for FOR variables.
Type 'HELP CALL' from a command prompt for a full list of parameter modifiers.
#echo off
if %1X==X echo Syntax: %0 "path"
rem The for loop doesn't actually loop. You can split strings with it, but in
rem this case we don't. So there is only one iteration in which %%X will
rem contain the full path.
rem Pass it %1, which is the first parameter. Note the quotes, which are
rem required if you don't add quotes around the parameter and optional (but
rem still valid) when you do.
for /F "delims=|" %%X in ("%1") do (
rem FOR LOOP variables can be used with certain modifiers, preceeded by a
rem tilde. In this case I'm using d and p, which stand for drive and path,
rem effectively trimming the file name from the path.
echo %%~dpX
rem The ~n modifier selects the file name only. ~x is for extension
echo %%~nxX
)

Change file extensions and name at once using batch file

I have a directory full of files output from some software as below:
Pending.001
Pending.002
Pending.003
etc.
I would like to use a .bat to rename them as below:
Pending001.csv
Pending002.csv
Pending003.csv
etc.
Any suggestions?
You could rename your files in a loop, using the modifiers ~n and ~x on the loop variable to extract, respectively, the name and the extension of each file to concatenate them in the new name. As the extension would be extracted together with the leading ., you would also need a variable to temporarily store the extension before removing the ..
Here's an example of how the above could be implemented:
#ECHO OFF
FOR %%I IN (Pending.*) DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
The delayed expansion is enabled because it is needed for the evaluation of ext. "Normal" expansion, which uses %, wouldn't work here because that way the variable would be expanded just once before the loop started, when the variable was still empty. In contrast, with the delayed expansion, the variable will be expanded every time the particular command containing it is executed, i.e. on every iteration of the loop too.
The above batch file would process files in the current directory, i.e. you would first need to change to the directory where the files need to be processed, then call the batch. Or, if you would be doing that in e.g. Windows Explorer, you would likely need to copy that batch to the directory with the files to process and call it from there.
Alternatively, though, you might want to call it with a parameter specifying the directory to process. To use the parameter, change the script like this:
#ECHO OFF
FOR %%I IN ("%~1\Pending.*") DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
Of course, you could also just specify a fixed path to the files if they are always in the same directory:
#ECHO OFF
FOR %%I IN ("D:\path\to\files\Pending.*") DO (
SET "ext=%%~xI"
SETLOCAL EnableDelayedExpansion
RENAME "%%I" "%%~nI!ext:~1!.csv"
ENDLOCAL
)
That way you would be able to call the batch from wherever you stored it.
Why don't you refer to these posts:
How can I mass rename files from the command line or using a 3rd party tool?
Bulk Rename Command
Bulk Rename Utility
Using batch files

Resources