Below batch script works great for copying the most recent file in a directory, but how can i rename the copied file accordingly?
pushd D:\sales\
for /f "tokens=*" %%a in ('dir /b ') do set newest=%%a
copy "%newest%" D:\test\
popd
The destination argument can be the directory to put the new file in, but you can also add the new filename to it. So instead of D:\test\ you could do something like D:\test\filename.ext
This improved code snippet renames your file to new_name.ext:
pushd D:\sales\
for /f "tokens=*" %%a in ('dir /b /o:-d /a:-d') do (
set "newest=%%~a"
goto :SKIP
)
:SKIP
copy "%newest%" "D:\test\new_name.ext"
popd
Improvements:
addition of new file name, of course...
defined sort order for dir to get the newest file first, and filtered out directories to get files only; the goto inside of for breaks the loop, so there is only one iteration; this might improve performance in case of a huge number of files;
inserted modifier ~ into for variable %%a to avoid any surrounding quotes; such are stated later at the destination in the copy command line;
Related
I have hundreds of sub folders coming off a c:\pdf\ folder.
I want to take the first pdf (sorted by name) in each sub folder and copy them to a single folder, say c:\QA\ so I can check the PDF for errors manually.
Can anyone help? Please!
I have this so far:
#echo off
cls
cd c:
cd c:\pdf\
for /r %%a in (*.pdf) do (
copy %%a c:\qa\%%~nxa
GOTO :EXIT
)
:Exit
Note File names are unique. Target dir is never a subdir of source. The baove code works for the first pdf in a sub folder but does not do the rest of the sub folders.
The New Technology File System (NTFS) returns a list of file names matching a wildcard pattern always sorted in alphabetical order. So for NTFS formatted partitions the following batch code is perhaps enough for this task.
#echo off
for /D %%D in ("C:\pdf\*") do if exist "%%D\*.pdf" call :CopyFirstFile "%%D"
goto :EOF
:CopyFirstFile
for %%F in ("%~1\*.pdf") do (
copy "%%F" C:\qa\
goto :EOF
)
goto :EOF
Please note that first FOR ignores subfolders with hidden attribute set. And the second FOR in subroutine CopyFirstFile ignores PDF files with hidden attribute set.
Another solution working also for File Allocation Table (FAT) partitions (FAT16, FAT32, exFAT) uses the command DIR to get the list of *.pdf files sorted by name.
#echo off
for /D %%D in ("C:\pdf\*") do if exist "%%D\*.pdf" call :CopyFirstFile "%%D"
goto :EOF
:CopyFirstFile
for /F "delims=" %%F in ('dir /A-D /B /ON "%~1\*.pdf"') do (
copy "%~1\%%F" C:\qa\
goto :EOF
)
goto :EOF
The command DIR ignores directories matching the pattern *.pdf and finds also hidden *.pdf files because of option /A-D. But COPY does not copy a hidden *.pdf file!
It would be perhaps better to use MOVE instead of COPY as on next run the batch file would copy the same files again if the folders in C:\pdf are not modified in the meantime.
The command lines below label CopyFirstFile are interpreted as subroutine called by the first FOR loop.
The first goto :EOF exits batch file processing once the first FOR loop iterating over all non hidden subdirectories of C:\pdf finished.
The second goto :EOF exits the second FOR loop and the subroutine after copying the first file found in the directory passed as first (and only) argument to the subroutine.
The third goto :EOF would not be really necessary as this command line should be never executed and is additionally also not needed when there are no more command lines in the batch file. But it is good practice to make sure that each block called as subroutine has as last line goto :EOF or alternatively exit /B which is exactly the same as goto :EOF.
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.
call /?
copy /?
dir /?
echo /?
for /?
goto /?
if /?
Here's some example code for you. It looks inside each directory and any potential subdirectory below C:\PDF, it does not look at files inside C:\PDF. If you're looking for something different then update your question accordingly.
#Echo Off
For /D /R "C:\PDF" %%A In (*) Do (
For /F "Delims=" %%B In ('Dir/B/A-D/O-N "%%A\*.pdf" 2^>Nul') Do (
Set "first=%%A\%%B")
SetLocal EnableDelayedExpansion
If Exist "!first!" Copy "!first!" "C:\QA"
EndLocal)
Pause
Please don't just use it, take your time to learn it by checking various references as well.
All you need to do is to combine the features of Dir & For . Now, You can simply analyze the code and modify it according to your need.
Hint for the Code:
CD /D "C:\PDF"
DIR /s /b *.pdf >a.txt
For /f "Tokens=*" %%A In (a.txt) Do (Copy /Y "%%A" "C:\QA")
Exit
And, it is almost all you need. :)
Have tried to rename files in a folder with this script, but its seems not to work
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET old=*.txt
SET new="c:\path to file that contains the listed names"
for /f "tokens=*" %%f in ('dir /b *.txt') do (
SET newname=%%f
SET newname=!newname:%old%=%new%!
move "%%f" "!newname!"
)
what am trying to achieve is my script should pick set of listed names in a file and rename each file in the specified folder accordingly
test this script
#echo off
set prefix=new
setlocal EnableDelayedExpansion
for /f "delims=" %%a in ('dir *.txt /b') do (
set name=%%~Na
set newName=%prefix%!name:~0,1!X!name:~1,2!!name:~3!
ren "%%a" "!newName!%%~Xa")
First you said you want to rename each file "accordingly" (accordingly to what?), and later in a comment you said you try to rename files "with a set of listed names in a file". This point cause several additional questions: Have this file one name in each line? Must the first file listed by dir /b *.txt match the first name listed in the file, and so on? Any other option? (Why do you use a move command to do a "rename"?).
Because the objective is not clear, we can not said if your code is right or not. However, this is what your code does. Suppose the first file is "firstFile.txt"; then this section:
SET newname=%%f
SET newname=!newname:%old%=%new%!
move "%%f" "!newname!"
is executed this way:
SET newname=firstFile.txt
SET newname=!newname:*.txt="c:\path to file that contains the listed names"!
Previous line replace from the beginning of newname until ".txt" (that is, the entire value) by "c:\path to file that contains the listed names", so the next line is executed this way:
move "firstFile.txt" ""c:\path to file that contains the listed names""
that correctly should move the file into the given path even if it contains a pair of quotes at each side.
If the objective would be "Rename files in a folder to the names listed in a text file one-by-one", then you must do a merge between two lists: the file list created by dir /b *.txt and the name list stored in the file.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET old=*.txt
SET new="c:\path to file that contains the listed names"
< %new% (for /f "tokens=*" %%f in ('dir /b %old%') do (
ren Read the next name from the redirected input file
SET /P newname=
ren "%%f" "!newname!"
))
If this is not what you want, please clearly describe the desired process...
I am trying to copy all .ini files from the Windows folder into a new folder I have already created. I need this to loop through for all users. Here is what I have but it only works for the last user, not each of them. This is a batch file.
for /r %%f in ("D:\Home\*.*\windows") do
set dir="%%d
for /r "%dir%\windows\" %%f in (*.ini) do (
copy %%f "%dir%\temp_ini"
))
pause
Please help :/ Thank you
You've got a few problems -- unterminated quote on the second line, not delaying the expansion of %dir% (and indeed, setting %dir% is unnecessary, anyway), illogical use of for /r in the first line, trying to recycle %%f in nested loops, and your *.* wildcard in the first line will only match directories containing a dot. You should also make sure the temp_ini directory is outside the scope of your search for ini files; otherwise, Windows will attempt to copy the contents of temp_ini\*.ini into itself recursively. Try this instead:
for /d %%I in ("D:\Home\*") do (
rem // create directory if not exist
if not exist "%%~I\temp_ini" md "%%~I\temp_ini"
rem // capture the output of dir /s /b
for /F "delims=" %%x in (
'dir /s /b "%%~fI\Windows\*.ini" 2^>NUL'
) do copy /y "%%~fx" "%%~I\temp_ini\"
)
pause
I'm a bit of a novice when it comes to .BAT files. Please, I'm in need of a batch file that will create folders based on the names of files in the local folder, and then move those files into their corresponding folders. The folder names need to be determined by the characters before the delimiter in the file names, in this case an underscore.
For example, it would take these files
june_jahdfjlkaluie2.xlsx
june_jahdfjlkaluie.xlsx
august_nnnvbcnkziery2.xlsx
august_nnnvbcnkziery.xlsx
december_bagjd_kasdgf.xlsx
december_byuueyiuyoi.xlsx
Create these folders
june
august
december
And move the files into those folders based on the characters before the underscore.
This is the code I have so far
#echo off &setlocal
for /f "delims=_" %%i in ('dir /b /a-d *.xls') do (
set "file=%%~i"
setlocal enabledelayedexpansion
set "folder=!file!"
mkdir "!folder!" 2>nul
move "!file!" "!folder!" >nul
)
endlocal
echo Did it work?
Pause
The batch file is able to make the folders based on the file names. However, when it attempts to move the files, it produces an error stating 'The process cannot access the file because it is being used by another process.' I've attempted several fixes, including creating a separate for command for moving the files, and nothing seems to work.
Any advice is greatly appreciated. Thank you.
#echo OFF
SETLOCAL
for /f "delims=_" %%i in ('dir /b /a-d *_*.xlsx') do (
mkdir "%%i" 2>nul
move "%%i_*.xlsx" "%%i" >NUL 2>nul
)
echo Did it work?
GOTO :EOF
would likely work and be easier.
Note that I've changed the target filemask to ….xlsX because the short filename for a .xslx file does not necessarily retain the *_*.xls format.
I want to rename all the sql files in a directory by prefixing them with the date and time the file was created.
I am new to command prompt, came up with below code from what I read but it is not working.
for /f "delims=*" %%I in ('dir *.sql /b /s') do (
set dt=%%~tI
for /f "delims=/: " %%a in ('%dt%') do (set mydate=%%a)
for /f "delims=/: " %%b in ('%dt%') do (set mytime=%%b)
ren %%~nI.sql %mydate%%mytime%_%%~nI.sql)
Something like this should work if the batch file is in the same directory as the sql files:
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=*" %%f in ('dir /b *.sql') do (
set createtime=%%~tf
set createtime=!createtime:/=!
set createtime=!createtime::=!
rename "%%f" "!createtime! %%f"
)
The 2nd and 3rd set createtime lines are replacing / and : (respectively) with null because those are invalid characters for a filename. If you prefer you could replace them with something else instead (e.g. -) by inserting this value to the right of the = character.
Note that the %%~t modifier used here (and in your example) actually gets the modified time of the file, not the created time. This would only be noticeable if your sql files are modified after they're created.
Also, there is nothing here to prevent it from prefixing the same files with additional timestamps if the script is executed more than once, so keep that in mind.
ren "%file" "%date:~0,2%.%date:~3,2%.%date:~6,4%-%time-somename.sql"