Batch file to find files in a directory - windows

I am creating a batch file to find if any files are present in the path d:\Users\gladiator\Desktop\my docs.
If any files are present, I need to trigger an email stating which are the files present in that path.
This is the snippet of my batch script.
#echo off
for /f "delims=" %%F in ('dir /b /s "d:\Users\gladiator\Desktop\my docs"') do set MyVariable=%%F
echo %MyVariable%files are present
But this script is not displaying all the files present in that location.
Could someone help me to modify the script so as to display all the files present in the location?

Try to use setlocal enabledelayedexpansion to start a local environment before your loop, as described here:
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/setlocal
Then, after you're done, use endlocal
When you expand the variable MyVariable use !MyVariable! which is how "delayed expansion" within a local environment works (rather than %MyVariable%).
Microsoft does not allow modification of an environment variable with set variable=... within a loop, without using "delayed expansion."
Here is an example with your code:
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%F in ('dir /b /s "d:\Users\gladiator\Desktop\my docs"') do (
set MyVariable=%%F
echo !MyVariable! file is present
)
endlocal
This will at least allow you to see the files present. Beyond that I'm not sure what you wish to do once filenames are detected.
If you want to fill MyVariable with all files found, then you can do this
#echo off
setlocal enabledelayedexpansion
set MyVariable=
for /f "delims=" %%F in ('dir /b /s "d:\Users\gladiator\Desktop\my docs"') do (
set MyVariable=!MyVariable! %%F
)
echo !MyVariable! files found
endlocal

Related

batch file remove prefix of directory name

I'm trying to remove a prefix of some directories.
I have many directories with names like '991234', '991235', '991236'. I want to remove the '99' from these folder names. The result needs to be a rename of the directories. They should be renamed to '1234', '1235', '1236'.
After some search I could write this script:
for /f "tokens=*" %%a in ('dir 99* /A:D /b') do ren "%%a" "00_%%a"
this script find all directories starting with '99' and call ren for each of them. The problem is that I could not remove the '99' part to apply in the folder name.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:: I use a test directory name that includes spaces to verify that the routine works with such directorynames
:: Use SET "sourcedir=." for the current directory
SET "sourcedir=u:\your files\t w o"
for /f "tokens=*" %%a in ('dir /A:D /b "%sourcedir%\99*"') do SET "dirname=%%a"&ECHO ren "%sourcedir%\%%a" "!dirname:~2!"
GOTO :EOF
The metavariable %%a needs to be assigned to a user variable for manipulation. Since the user variable will change value within the code block, delayedexpansion needs to be invoked.
See for /? and set /? for documentation, as well as Stephan's DELAYEDEXPANSION link: https://stackoverflow.com/a/30284028/2128947
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the directories.
Always verify against a test directory before applying to real data.

search the requested file in subfolders and copy to destination

I am trying to copy the listed files in file_list.txt to destination folder from source location, source folder has subfolders. my batch should be capable to search the file in source subfolders and copy to destination folder. same for copy all files with extension .exe. what is wrong with my code. I think, I have missed to search subfolders data. don't know what is the command. please help.
#Echo Off
SETLOCAL ENABLEDELAYEDEXPANSION
#color 0a
cls
set "dest=D:\destination"
set /p source=Select source path:
for /R %%f in (%source%/*.exe) do copy %%f "%dest%"
echo Copy requested files
for /f %%f in (file_list.txt) do (
for /f "tokens=*" %%F IN ('dir /S /B /A:-D "%source%/%%f"') Do (
copy "%%F" "%dest%\%USERNAME%"
)
)
pause
ENDLOCAL
I cannot see anything obviously wrong with the code you've posted, although there are possibilities for errors. You have not provided sufficient information, about your current directory, the content of the text file, how the script is invoked or any debugging information.
The following version of your code, requires that you put your file listing text file into the variable definition on line five. I've assumed that the batch file is in the same location as the file listing, and therefore used %~dp0. If it is in the current directory instead, then replace that with %CD%\, and obviously the fully qualified absolute path if neither.
Next I use some validation to try to ensure that the source, destination, and user input exist. The input location will then become the current directory.
Your provided commands are then run, before the curent directory is returned to its original location.
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Color 0A
Set "listdir=%~dp0filelist.txt"
Set "dest=D:\destination"
If Not Exist "%listdir%" GoTo :EOF
If Not Exist "%dest%\" GoTo :EOF
:Ask
ClS
Set "source="
Set /P "source=Select source path: "
If Not Defined source GoTo Ask
PushD "%source:"=%" 2> NUL || GoTo Ask
For /R %%G In (*.exe) Do Copy /Y "%%G" "%dest%"
Echo Copy requested files
For /F "UseBackQ EOL=? Delims=" %%G In ("%listdir%"
) Do For /F "Delims=" %%H In ('Dir "%%~nxG" /S /B /A:-D 2^> NUL'
) Do Copy /Y "%%H" "%dest%\%UserName%"
PopD
Pause
Feel free to try the code, and provide some proper debugging information if it still fails to work as intended.

How to rename files in subfolder into a specific format

I have files named as RabcdYYMMKKACCOUNT.TXT in the Subfolders of a folder where YYMM is year, month this will change. KK is another identifier, I want all the files to be renamed to MSFKKDNB.ABC, the KK is the identifier in the input file.
Below is the one i tried and the result of it:
FOR /R %%f IN (*account.txt) DO REN "%%f" *dnb.abc
R00531706AUAccount.txt is renamed to R00531706AUAccount.txtdnb.abc
but the output should be MSFAUDNB.abc
This could be done for example with:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /R %%I in (???????????account.txt) do (
set "FileName=%%~nI"
set "NewFileName=MSF!FileName:~9,2!DNB.abc"
if not exist "%%~dpI!NewFileName!" (
ren "%%~fI" "!NewFileName!" 2>nul
if not exist "%%~dpI!NewFileName!" echo Failed to rename file: "%%~fI"
) else (
echo Cannot rename file: "%%~fI"
)
)
endlocal
The file name of found account text file is assigned to environment variable FileName.
The new name for the file is created by concatenating the fixed parts MSF and DNB.abc with the 2 characters to keep from file name using string substitution and delayed expansion.
Next it is checked if a file with new name does not already exist. Is this the case the file renaming is done otherwise an error message is output.
After renaming the file it is checked if that was successful. A slightly different error is output if renaming failed for example because of a sharing violation.
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 /?
if /?
ren /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators.
Try this:
#Echo Off
For %%A In ("*account.txt") Do (Set "_=%%~nA"
SetLocal EnableDelayedExpansion
Ren "%%A" "MSF!_:~-9,2!DNB.abc"
EndLocal)
I would probably do it the following way, provided that the files to rename are located in immediate sub-directories (YYMM) of the given root directory and nowhere else:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_ROOT=." & rem // (specify path to the root directory)
for /D %%D in ("%_ROOT%\????") do (
for %%F in ("%_ROOT%\%%~nxD\R??????????Account.txt") do (
set "FDIR=%%~nxD" & set "FILE=%%~nxF"
setlocal EnableDelayedExpansion
ECHO ren "!_ROOT!\!FDIR!\!FILE!" "MSF!FILE:~9,2!DNB.abc"
endlocal
)
)
endlocal
exit /B
If you want to check whether both the sub-directory name and the year/month portion of the file names are purely numeric, you could use the following script:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_ROOT=." & rem // (specify path to the root directory)
for /F "delims= eol=|" %%D in ('
dir /B /A:D "%_ROOT%\????" ^| ^
findstr "^[0123456789][0123456789][0123456789][0123456789]$"
') do (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "%_ROOT%\%%~nxD\R??????????Account.txt" ^| ^
findstr "^R....[0123456789][0123456789][0123456789][0123456789].."
') do (
set "FDIR=%%~nxD" & set "FILE=%%~nxF"
setlocal EnableDelayedExpansion
ECHO ren "!_ROOT!\!FDIR!\!FILE!" "MSF!FILE:~9,2!DNB.abc"
endlocal
)
)
endlocal
exit /B
If you want to check whether the sub-directory name matches the year/month (YYMM) portion of the file names, replace the pattern R??????????Account.txt by R????%%~nxD??Account.txt (for both scripts).
After having verified the correct output of either script, remove the upper-case ECHO commands to actually rename any files!
Basically, both scripts use sub-string expansion to extract the identifier part (KK) from the file names. Since there are variables set and read in the same block of code, delayed expansion is required for that. The second approach does not list the sub-directories and files by standard for loops, it uses the dir command, findstr to filter their names and a for /F loop to capture the resulting output for both sub-directories and files.

How to return the newest file from each sub-directory in Windows command line using batch

I am using batch script for windows command line on windows 7. I am currently trying to get the newest file from each sub directory and print them to the screen. For example, if I have:
C:\Home\Hi\Folder1\a 01/05/2016
C:\Home\Hi\Folder1\b 01/10/2016
C:\Home\Hi\Folder2\x 03/05/2016
C:\Homeh\Hi\Folder2\y 03/1/2016
It would return: folders b and x.
I have written some script to attempt this, but it only returns the newest file in the last directory which in my example would be x. The script is:
FOR /R "C:\Users\Maxx\Desktop\tools" %%G in (.) DO (
Pushd %%G
FOR /F %%I IN ('DIR %%G /B /O:D') DO SET NEWEST=%%I
ECHO %NEWEST%
Popd )
Echo "back home"
If anyone knows how to get the newest file from each subdirectory that would be great.
Note: I have looked at various other examples such as: Generate a list of the newest file in each subdirectory in windows batch, which has been very helpful in building what I have now, but ultimately it did not work.
You need to apply delayed expansion as you are writing and reading variable NEWEST within the same block of code:
setlocal EnableDelayedExpansion
for /R "C:\Users\Maxx\Desktop\tools" %%G in (.) do (
pushd "%%~G"
for /F %%I in ('dir "%%~G" /B /O:D') do set "NEWEST=%%I"
echo !NEWEST!
)
popd
echo back home
endlocal
Alternatively, replace echo %NEWEST% by call echo %%NEWEST%%:
for /R "C:\Users\Maxx\Desktop\tools" %%G in (.) do (
pushd "%%~G"
for /F %%I in ('dir "%%~G" /B /O:D') do set "NEWEST=%%I"
call echo %%NEWEST%%
)
popd
echo back home
In addition, I improved quoting.
#ECHO OFF
SETLOCAL
FOR /R "C:\106x" %%G in (.) DO (
Pushd "%%G"
SET "first="
FOR /F "delims=" %%I IN ('DIR . /a-d /B /O:-D 2^>nul') DO IF NOT DEFINED first SET first=Y&ECHO %%~dpI
Popd
)
Echo "back home"
GOTO :EOF
For each directory, go to the directory, clear a flag first, scan the directory for files (not directories), basic format, reverse-date order, suppressing any "file not found" reports from empty directories.
On finding the first (ie youngest) file set the flag first and report the filename - or parts of the filename you require.
Once first has been set, the report mechanism will not be invoked as if defined works on the current value of the variable.
Please note that when specifying dates, it's advisable to state the format that you are using - or at least use a date where the day number is >12, which should be adequate. For instance, your date "01/10/2016" may be interpreted as Jan 10th or Oct 1st, depending on the respondent's locale. "13/10/2016" or "10/13/2016" would make the issue obvious.

Make subfolder names from part of file name and copy files with Robocopy

Is it posible to copy and make directories automatically from file name substrings using Robocopy?
I mean i have files like these. LAJ00306130201004626.rc the first 8 chararacters are control number (LAJ00306=control number) this would be the name of the folder and the rest are the date and time (Date=130201) (time=004626).
LAJ00306130201004626.rc
LAJ00306130202004626.rc
LAJ00306130203004626.rc
LAJ00307130201004626.rc
LAJ00307130202004626.rc
and i would like to copy and create folders from the file name like under and copy the files mentioned before in the new folders.
LAJ00306
LAJ00307
I hope to be clear if necessary ask me for more information
try this, look at the output and remove the echos before MD and ROBOCOPY, if it looks good:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcefolder=."
SET "targetfolder=X:\data"
CD /d "%sourcefolder%"
FOR %%a IN (*.rc) DO (
SET "fname=%%a"
SET "folder=!fname:~0,8!"
SET "$!folder!=1"
)
FOR /f "delims=$=" %%a IN ('set "$"') DO (
ECHO MD "%targetfolder%\%%a" 2>nul
ECHO ROBOCOPY "%sourcefolder%" "%targetfolder%\%%a" "%%a*.rc"
)
Set sourcefolder and targetfolder for your folder tree.
Try this:
#echo off
pushd "c:\source folder"
setlocal enabledelayedexpansion
for %%a in (*.rc) do (
set "name=%%a"
robocopy "%cd%" "%%a" "D:\target directory\!name:~0,8!"
)
popd
Answers to your questions are:
pushd "drive:\path" makes the location the current working directory.
popd restores the last working directory
setlocal enabledelayedexpansion allows you to change and use variables within a loop, using the !variable! syntax.
If your 2000 files are in a single folder then it should work - but test it on some sample files first so that you can see how it will work.
#ECHO OFF
SETLOCAL
SET "sourcedir=."
SET "destdir=c:\destdir"
FOR /f "tokens=1*delims=_" %%i IN (
'dir /b /a-d "%sourcedir%\*_*."'
) DO XCOPY /b "%sourcedir%\%%i_%%j" "%destdir%\%%i\"
GOTO :EOF
This should accomplish the task described. You'd need to set up the source and destination directories to suit, of course. Add >nul to the end of the XCOPY line to suppress 'copied' messages.

Resources