search the requested file in subfolders and copy to destination - windows

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.

Related

How can I move specific files from multiple subfolders to their respective parent folder? (Windows batch)

I have the following file and folder structure (using real names):
Carabidae/Pterostichinae/FolderNameXXX/dor/StackXXX/files.tif
My problem is that I need to get one specific file, PM*.*, from the StackXXX folders into their respective /dor parent folders. The StackXXX folder can then be deleted.
There are hundreds of FolderName. Ideally I would like a batch file I can run from the Carabidae folder.
This needs to be a batch file because there will be new FolderNames added constantly.
After a lot of searching, I found a semi-working solution from this StackOverflow answer:
for /f "delims==" %%i in ('dir /a:d /b') do for /f "delims==" %%f in ('dir %%i /a:d /b') do (move "%%i\%%f\PM*.*" "%%i"&&rd "%%i\%%f" /s /q)
It moves the file and deletes the folder, just as I want. But the problem is that it only works when run from a FolderName folder, which defeats the time-saving purpose of the script. I don't know how to modify it to recurse into subfolders so I can run it from the top folder.
Thank you very much for any help!
#ECHO OFF
SETLOCAL
SET "sourcedir=u:\Carabidae"
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /s /a-d "%sourcedir%\pm*.*" '
) DO IF EXIST "%%a" (
FOR %%p IN ("%%~dpa..\.") DO IF /i "%%~nxp"=="dor" (
ECHO %%a|FINDSTR /i "\\dor\\Stack" >NUL
IF NOT ERRORLEVEL 1 (
ECHO MOVE /y "%%~dpa\pm*.*" "%%~dpa..\"
ECHO RD /s /q "%%~dpa"
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Find all of the pm*.* files, filenames to %%a
Ensure the parent directory is dor and ensure that \dor\stack\ is in the path. If so, move the file(s) and remove the directory.
The if exist gate ensure no hiccoughs if a target directory contains more than one pm*.* file.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.
Add >nul at the end of the move command to suppress the move-report if required.
As usual, I'd suggest you test against a representative subtree first.
Here is a possible solution, given that only the XXX parts in your path sample are variable:
rem // Enumerate `FolderName*` directories:
for /D %%R in ("Carabidae\Pterostichinae\FolderName*") do (
rem // Enumerate `Stack*` sub-directories within `dor` sub-directories:
for /F "delims= eol=|" %%D in ('dir /B /A:D "%%~R\dor\Stack*"') do (
rem // Check for `PM*.*` files in `Stack*` sub-directories:
(
rem // Enumerate `PM*.*` files:
for /F "delims= eol=|" %%F in ('dir /B /A:-D "%%~R\dor\%%D\PM*.*"') do (
rem /* Move `PM*.*` file one directory level up, overwriting
rem an already existing file, if applicable: */
ECHO move /Y "%%~R\dor\%%D\%%F" "%%~R\dor\%%F"
)
) && (
rem /* Remove `Stack*` sub-directory after file movement;
rem this is skipped if no `PM*.*` files have been found in the `Stack*`
rem sub-directory, so when the `for /F %%F` loop did never iterate: */
ECHO rd /S /Q "%%~R\dor\%%D"
)
)
)
After having successfully tested whether or not the correct items are returned, remove the upper-case ECHO commands to actually move PM*.* files and remove Stack* directories!

Moving files from Subfolders into root directory, but not copying them to the next directory when ran again

I have a folder that contains subfolders with MP4 files. I'm trying to write a script that will move the MP4 files out of the subfolders into the root folder when ran. The batch file I wrote is working, but when the batch script runs again for new subfolders, the MP4 files that were already copied to the root folder, get moved up another level in the file structure. For example:
C:\MainRoot\Root\Subfolder\media.mp4
When script is ran, 'media.mp4' gets moved up to C:\Root\media.mp4 as desired.
But since I need the script to run on a scheduled task. The next time the script runs I get the following:
C:\MainRoot\media.mp4
Instead of just the MP4 file staying in C:\MainRoot\Root.
Here's my batch file so far to copy the mp4 files:
set root_folder=C:\MainRoot\Root
for /f "tokens=1* delims=" %%G in ('dir %root_folder% /b /o:-n /s ^| findstr /i ".mp4" ') do (
move /y "%%G" "%%~dpG..\%%~nxG"
)
What do I need to modify so that once moved, the MP4 files will stay in place?
Any help would be greatly appreciated!
Since all your source files seem to be at a certain directory level, a for /D loop could be wrapped around your for /F loop, which parses the output of a non-recursive dir command line (no /S):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=C:\MainRoot\Root"
set "_PATTERN=*.mp4"
rem // Loop through sub-directories:
for /D %%D in ("%_ROOT%\*") do (
rem // Loop through matching files:
for /F "eol=| delims=" %%F in ('dir /B "%%~fD\%_PATTERN%"') do (
rem // Avoid overwriting destination file:
if not exist "%_ROOT%\%%~nxF" (
rem // Move matching file one level up:
move /Y "%%~fD\%%~nxF" "%_ROOT%\%%~nxF"
)
)
)
endlocal
exit /B
If you are happy to overwrite as in your provided example then something as simple as this may suit your purpose:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /R %%G In (*.mp4) Do If /I NOT "%~dpG"=="%root_folder%\" Move "%%G">Nul 2>&1
If the files are only one folder deep you may prefer this:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /D %%G In (*) Do Move "%%G\*.mp4">Nul 2>&1

Find all files and copy to another destination keeping the folder structure

I have a folder structure with a bunch of *.jpg files scattered across the folders.
Now I want to find some files listed in a CSV file (one column only) or a text file line by line like
one.jpg
ten.jpg
five.jpg
and copy all those *.jpg files to another folder keeping the folder structure like:
outputfolder\somefolder\somefolder\one.jpg
outputfolder\somefolder\ten.jpg
outputfolder\somefolder\somefolder\somefolder\five.jpg
How can I achieve this?
Here is what I've tried
#echo off
CLS
REM CHECK FOR ADMIN RIGHTS
COPY /b/y NUL %WINDIR%\06CF2EB6-94E6-4a60-91D8-AB945AE8CF38 >NUL 2>&1
IF ERRORLEVEL 1 GOTO:NONADMIN
DEL %WINDIR%\06CF2EB6-94E6-4a60-91D8-AB945AE8CF38 >NUL 2>&1
:ADMIN
REM GOT ADMIN RIGHTS
COLOR
1F ECHO Please wait...
FOR /R "%~dp0" %%I IN (.) DO
for /f "usebackq delims=" %%a in ("%~dp0list.txt") do
echo d |xcopy "%%I\%%a" "C:\B2B_output_files" /e /i
COLOR 2F
PAUSE
GOTO:EOF
:NONADMIN
REM NO ADMIN RIGHTS
COLOR 4F
pause
GOTO:EOF
Stack Overflow is not a free code writing service, see help topic What topics can I ask about here?
However, I have nevertheless written the entire batch code for this task. Learn from this commented code and next time try to write the batch code by yourself and ask only if you stick on a problem you can't solve by yourself after several trials and not finding a solution on Stack Overflow or any other website.
The paths of source and target base folder must be defined at top of the batch script below.
The text file containing the name of the files to copy line by line must be named FileNames.txt and must be stored in source base folder with using batch code below.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Define source and target base folders.
rem Note:
rem The paths should not contain an equal sign as then the
rem string substitutions below would not work as coded. The
rem target base folder can be even a subfolder of the source
rem base folder.
set "SourceBaseFolder=C:\Temp"
set "TargetBaseFolder=C:\Temp\OutputFolder"
rem Set source base folder as current directory. The previous
rem current directory is restored by command endlocal at end.
if not exist "%SourceBaseFolder%\*" (
echo %~nx0: There is no folder %SourceBaseFolder%
set "ErrorCount=1"
goto HaltOnError
)
cd /D "%SourceBaseFolder%"
if not exist "FileNames.txt" (
echo %~nx0: There is no file %SourceBaseFolder%\FileNames.txt
set "ErrorCount=1"
goto HaltOnError
)
rem For each file name in text file FileNames.txt in
rem source base folder the loops below do following:
rem 1. Search recursively for a file with current file name
rem in entire directory tree of source base folder.
rem 2. If a file could be found, check its path. Skip the
rem file if the path of found file contains the target
rem folder path to avoid copying files to itself. This
rem IF condition makes it possible that target base
rem folder is a subfolder of source base folder.
rem 3. Create the folders of found file relative to source
rem base path in target base folder. Then check if this
rem was successful by verifying if the target folder
rem really exists and copy the file on existing folder or
rem output an error message on failure creating the folder.
set "ErrorCount=0"
for /F "usebackq delims=" %%N in ("FileNames.txt") do (
for /R %%J in ("%%N*") do (
set "FilePath=%%~dpJ"
if "!FilePath:%TargetBaseFolder%=!" == "!FilePath!" (
set "TargetPath=%TargetBaseFolder%\!FilePath:%SourceBaseFolder%\=!"
md "!TargetPath!" 2>nul
if exist "!TargetPath!\*" (
echo Copying file %%~fJ
copy /Y "%%~fJ" "!TargetPath!" >nul
) else (
set /A ErrorCount+=1
echo Failed to create directory !TargetPath!
)
)
)
)
:HaltOnError
if %ErrorCount% NEQ 0 (
echo.
pause
)
endlocal
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 /? ... for an explanation of %~nx0
copy /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
pause /?
rem /?
set /?
setlocal /?
And read also the Microsoft article about Using command redirection operators to understand 2>nul for suppressing error messages written to STDERR.
The following code should do what you asked for:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LISTFILE=copylist.txt"
set "SOURCE=.\source"
set "DESTIN=.\destin"
for /F "usebackq eol=| delims=" %%L in ("%LISTFILE%") do (
for /F "eol=| delims=" %%F in ('
cd /D "%SOURCE%" ^
^& xcopy /L /S /I /Y ".\%%~L*" "%TEMP%" ^
^| findstr /I /R "^\..*\\%%~L$"
') do (
2> nul md "%DESTIN%\%%F\.."
copy /B /-Y "%SOURCE%\%%F" "%DESTIN%\%%F"
)
)
endlocal
exit /B
It relies on the fact that xcopy outputs relative paths to the console if a relative source path is given, and that it features a switch /L that tells it not to copy anything but list what would be copied without the switch. There is also the switch /S which defines to search for the source item recursively also within subdirectories.
There is a small problem though which requires to be worked around: xcopy /S only walks through subdirectories if source contains a wildcard * or ?, but not if a dedicated file name is given. That is why * is appended to the file name. Since this could also match some unintended items of course, findstr is used to filter them out.
So basically there is a for /F loop that iterates through the items listed in the text file copylist.txt. Within this loop another for /F is nested that enumerates the output of the aforementioned findstr-filtered xcopy /L /S output, which receives the items of the outer loop one after another. The embedded cd command ensures to be in the source directory. The destination of xcopy is just an existing directory to avoid error messages (remember nothing is actually copied due to /L).
The inner loop bopy contains an md command that creates the destination directory (tree), if not existing (2> nul avoids error messages if has already been created earlier), and a copy command which actually performs the copying activity; the switch /-Y defines to prompt the user in case an item already exists at the destination location, you can change it to /Y to overwrite without asking.

Windows batch to add prefix to file names, why added twice?

In order to add a simple "hello" prefix to all pdf files in a folder I'm using this batch file:
FOR %%F IN (*.pdf) DO (RENAME "%%F" "hello%%F")
Saved this into a "rename.bat" file and placed it into the folder I need the files to be renamed. Then I just double click on "rename.bat".
This almost works but the 1st file gets the prefix added twice.
Let's say in the folder I have: A.pdf, B.pdf, C.pdf, they get converted into:
hellohelloA.pdf
helloB.pdf
helloC.pdf,
Do you know what's wrong in the batch file?
I noticed it always does this when files are more than one. It works ok when there is only one file in the folder, but it is not very useful :-).
/f removes the issue of recapturing an existing file:
FOR /f "delims=" %%F IN ('DIR /a-d /b *.pdf') DO (RENAME "%%F" "hello%%F")
#echo off
echo.
echo. Add Whatever Prefix...
echo.
echo. You Want To Add...
echo.
echo. To The Filename...
echo.
set /p variable=" > "
setlocal enabledelayedexpansion
for /f "delims=" %%a in (' dir /b /a-d *.pdf') do (
set oldName=%%a
Set newName=%variable%!oldName!
Ren "!oldName!" "!newName!"
)
exit
This works well..... Try It Out ... No Double Prefix... Ever.

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