Find multiple files' paths with the same file name - batch-file

I tried to write a batch script that find all the paths of files that have the same name as the input string. right now it can find only the first file found, and i cant think of a way to make it list multiple files locations. I am not very experienced and I need some help.
this is part of the script code:
:start
cls
echo Enter file name with extension:
set /p filename=
echo Searching...
for %%a in (C D E F G H U W) do (
for /f "tokens=*" %%b in ('dir /s /b "%%a:\%filename%"') do (
set file=%%~nxb
set folderpath=%%~dpb\
::the path of the file without the filename included "C:\folder\folder\"
set fullpath=%%b
::the path of the file with the filename included "C:\folder\folder\file"
goto break
)
)
:notfound
cls
echo Enter file name with extension:
echo %filename%
echo File Not Found!
ping localhost -n 4 >nul
goto start
:break
if "%folderpath:~-1%"=="\" set folderpath=%folderpath:~,-1%
cls
echo ? %filename% found
echo %fullpath1%
echo %fullpath2%
echo %fullpath3%
--- || ---
I want the script to search the computer and list every encountered files with the same name and I want to be able to put those files' paths into different variables.
For example, if readme.txt is the input, then I want the list of all the paths of all the files with that specific name (readme.txt) and I want to set variable for each path so I can use it after that.
example:
input:
readme.txt
output:
3 files found
C:\folder\folder\readme.txt
C:\folder\folder\folder\readme.txt
D:\folder\readme.txt
variables:
path1 = C:\folder\folder\readme.txt
path2 = C:\folder\folder\folder\readme.txt
path3 = D:\folder\readme.txt

Here is a single script which will performs the task requested. It searches all drives for your input filename with extension, puts each found full file path into a variable, then output those variables for you. I will not be tailoring the script for any new changes after this response, advising on how to integrate it into the rest of your script or supporting any changes you may subsequently make.
#Echo Off
Set/P "SearchTerm=Enter file name with extension: "
Set "i=0"
For /F "Skip=1" %%A In ('WMIC LogicalDisk Where^
"DriveType>1 And DriveType!=5 And FreeSpace Is Not Null" Get DeviceID'
) Do For %%B In (%%A) Do (For /F "Delims=" %%C In (
'Where/F /R %%B\ "%SearchTerm%"2^>Nul') Do (Set/A i+=1
Call Set FullPath[%%i%%]=%%C))
If %i% LSS 1 (Echo= %SearchTerm% Not Found) Else (
Echo= %SearchTerm% had %i% match(es^)
For /L %%A In (1,1,%i%) Do (
Call Echo= %%%%FullPath[%%A]%%%% = %%FullPath[%%A]%%))
Timeout -1 1>Nul
Please be warned that searching many locations and putting many files into variables may over burden your system and cause issues.

Related

Batch File - When copying files sometimes it shows The system cannot find the path specified for all the file or for majority of file

i am making a file selector which would randomly copy files from one folder to another code works quite fine but sometimes it shows The system cannot find the path specified for all or majority of files i don't know what went wrong can please someone help
my code
#echo off
setlocal enabledelayedexpansion
set num=0
cls
set /p input= enter the number of files you want:
set /p address= enter the address of your files:
md SelectedFiles
pushd "%address%" || goto :EOF
set /a num=%num%+1
for /f "tokens=1,* delims=[]" %%i in ('dir /b /s /a-d ^| findstr /RV "[.]jpg [.]png" ^| find /v /n ""') do (
set "file%%i=%%~j"
set "cnt=%%i"
)
for /l %%c in (1,1,%input%) do (
set /a rand=!random! %% !cnt!
for %%r in (!rand!) do copy "!file%%r!" "%address%\SelectedFiles" | clip
)
echo your files have been copied
pause
popd
Try, as a replacement for your for /l loop
for /l %%c in (1,1,%input%) do (
set /a rand=1 + !random! %% !cnt!
for %%r in (!rand!) do (
copy "!file%%r!" "%address%\SelectedFiles" | clip
for %%s in (!cnt!) do set "file%%r=!file%%s!"
set /a cnt-=1
)
)
Your filenames are currently being assigned to file1..file!cnt!.
You are then generating rand as 0..cnt-1, so there is a probability that you will choose file0 which does not exist and no possibility of choosing file!cnt!
There is also a possibility of re-choosing a file.
You should make sure that input is not greater than cnt.
My suggested code simply makes the range 1..cnt, then when a file has been processed, moves the very last filename (file!cnt!) over the chosen name and reduces cnt since there is one fewer filename in the list.
NOTE: Since the |clip is piping from a copy statement for one file only, it should only ever generate 1 file(s) copied. on the clipboard

Creating List of Folders from File Names

I have a folder containing many files named as such: JBMA_23456.docx, JMRI_21456.docx, CM_22554.docx, QUA_11224.docx. How do I create a sub-folder for each file bearing the same name as the file but without the .docx file extension? Additionally, I want to store the filename only as variables.
For example, I need to create a sub-folder named JBMA_23456 from the document
JBMA_23456.docx. Can anyone point me in teh right direction?
#echo off
for %%A in (*.docx) do if not exist "%%~nA" md "%%~nA"
This creates a folder with the same name as each .docx file.
View modifiers in for /? or in call /?. The n modifier is the name.
Path modifiers:
dpnx is drive, path, name and extension.
Here's an example batch file which attempts to perform the tasks as laid out in your question:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "BaseDir=C:\Users\Compo\Desktop\test"
Set "FileExt=.docx"
For /F "Delims==" %%A In ('Set var[ 2^>Nul') Do Set "%%A="
Set "i=0"
For /F "Delims=" %%A In ('Where "%BaseDir%":*%FileExt% 2^>Nul') Do (Set /A i+=1
Call Set "var[%%i%%]=%%~nA"
If Exist "%%~dpA%%~nA\" (Echo Sub-Folder %%~nA already exists in %BaseDir%
) Else (Set /P "=Creating sub-folder %%~nA in %BaseDir%"<Nul
MD "%%~dpA%%~nA">Nul 2>&1 && (Echo= was successful) || Echo= failed))
Set var[ 2>Nul
Pause
In order to use it, you would first ensure that the directory holding your files, (excluding any trailing backslash), is placed between the = and " on line 4, and the single file extension, (including the leading period, .), similarly on line 5.
It is not entirely clear what you are asking for...
Anyway, here is the code i made
echo off
chcp 65001
cls
for /f "usebackq delims=." %%0 in (`dir /b "*.docx"`) do (
set filename=%%0
md %filename%
)
cmd /k
It creates a new folder for every file. Feel free to ask if this was not what you expected

Remove duplicate files in a directory

I have a working script, (below), which compares files, by size only, and if one or more of the files have different size, it shows on the .bat screen.
#echo off
setlocal EnableDelayedExpansion
rem Group all file names by size
for /R %%a in (*.*) do (
set "size[%%~Za]=!size[%%~Za]!,%%~Fa"
)
rem Show groups that have more than one element
for /F "tokens=2,3* delims=[]=," %%a in ('set size[') do (
if "%%c" neq "" echo [%%a]: %%b,%%c
)
pause
But I need more!
I also need the script delete duplicate files, keeping just one. For example, if there are 3 files of the same size but with different names, the script should choose one to keep, deleting the other 2.
#LotPings, i tried with 2 .pdf files, and appeared this message in the pic below:
#LotPings
Now it recognized fine! But it doesn't deleting the duplicate, just recognizing.... Look the image below:
I think treating files with same size as same content is a bit naive.
If in doubt better do a binary compare with fc.
Your way of stuffing %%~Fa into a string without quoting every single name possibly containing spaces can be problematic in further processing.
If the files are identical you could create links.
You know that for /r will recurse into subdirs?
The following batch will process the size[] array differently passing the size and content to a subroutine which keeps the first file and (only echos) the del command.
:: Q:\Test\2018\06\06\SO_50723488.cmd
#echo off & setlocal
rem Group all file names by size
for /R %%a in (*.*) do call set size[%%~Za]=%%size[%%~Za]%%,"%%~Fa"
rem Process groups
for /F "tokens=2* delims=[]=," %%a in ('set size[') do Call :Sub %%a %%b
pause
Goto :Eof
:Sub
If "%~3"=="" (Set "size[%1]="&goto :EOf)
Echo ========================================
Echo processing %*
Echo Keep %2
Shift&shift
:loop
Echo Del %1
if not "%~2"=="" (shift&goto :loop)
Sample output:
> Q:\Test\2018\06\06\SO_50723488.cmd
========================================
processing 0 "Q:\Test\2018\05\03\Text3.txt","Q:\Test\2018\05\27\log.html"
Keep "Q:\Test\2018\05\03\Text3.txt"
Del "Q:\Test\2018\05\27\log.html"
========================================
processing 14 "Q:\Test\2018\05\03\Text1.txt","Q:\Test\2018\05\15\HP-G1610-20180515.json"
Keep "Q:\Test\2018\05\03\Text1.txt"
Del "Q:\Test\2018\05\15\HP-G1610-20180515.json"
========================================
processing 21 "Q:\Test\2018\05\12\text1.txt","Q:\Test\2018\05\12\text2.txt"
Keep "Q:\Test\2018\05\12\text1.txt"
Del "Q:\Test\2018\05\12\text2.txt"
========================================
processing 22 "Q:\Test\2018\05\20\2.txt","Q:\Test\2018\05\22\version.ps1"
Keep "Q:\Test\2018\05\20\2.txt"
Del "Q:\Test\2018\05\22\version.ps1"
========================================
processing 288 "Q:\Test\2018\05\11\RawData.txt","Q:\Test\2018\05\23\SO_50478080.ps1"
Keep "Q:\Test\2018\05\11\RawData.txt"
Del "Q:\Test\2018\05\23\SO_50478080.ps1"
The following script removes duplicate files in the current directory. It leaves one file, and removes rest of its duplicates. I developed the script for Windows 10, so it might not work for other Windows versions.
The advantage of this script is it not only checks the last modified date and time, but also the file size. Let's say you have a text file with *** symbols? you can turn them all ### symbols, and still occupy the same space. The script checks the last modified date, and time along with its size to ensure both the files are identical, otherwise it doesn't remove any file.
setlocal enabledelayedexpansion
echo(
echo "This program removes duplicate files in the current directory."
echo "Warning: Take a backup of the current directory to avoid accidents"
PAUSE
echo(
set path=%cd%
set /A count=0
for %%a in (*.*) do (
for %%b in (*.*) do (
if exist "%%b" if %%a neq %%b (
if "%%~Ta %%~Za" equ "%%~Tb %%~Zb" (
echo "%%a File is deleted"
set /A count+=1
del "%%a"
)
)
)
)
echo(
echo "---------"
echo "!count! Duplicate Files were deleted in the current directory"
echo "---------"
echo(
endlocal
PAUSE
If you have any problems report me at
https://github.com/donqq/Duplicate-File-Remover/

Double FOR loop to move files

Thanks for any help in advance.
I am trying to make a batch file to move files in some folder.
Just a bit background.
I have a folder and the structure as below:
c:\test
app1\app1.exe
app2\app2.exe
app3\app3.doc
xx[xx].exe
xx2\xx2.exe
xx3\xx3.EXE
In other words, I have a folder that contains a few sub folders, each of the sub-dir has some files. What I want to do is using a script, loop all the folders, move all files contain "app" to folder app, then move all files have "xx" to folder xx - in order to minimize the effort, I've already created these two folders so the script doesn't need to decide if it has to make a new dir.
Below is my script,
#echo off
rem loop xx
FOR /r "C:\test\" %%G in (*xx*.*) DO (
Echo Found file - %%G
copy %%G c:\testf\xx\
set pathname=%%G
for %%K in ("%pathname%") do ( set filepath=%%~dpK
set filename=%%~nxK
echo Filepath is %filepath%
echo %filename% >> c:\output.log )
echo full is %pathname% )
rem loop app
FOR /r "C:\test\" %%H in (*app*.*) DO (
Echo Found file - %%H
copy %%H c:\testf\app\
set pathname=%%H
for %%L in ("%pathname%") do ( set filepath=%%~dpL
set filename=%%~nxL
echo Filepath is %filepath%
echo %filename% >> c:\output.log )
echo full is %pathname% )
Echo "All Done"
The current output log shows
xx3.EXE
xx3.EXE
xx3.EXE
app3.EXE
app3.EXE
app3.EXE
and xx files were sent to xx folder only but app files didnt.
Could I have any help to deal with this problem?
I really appreciate any help you can provide.
Perhaps the path of your app files includes spaces - that would break the COPY command unless you include quotes.
Your script is much more complicated than need be. There isn't any need for the inner loop. You can also eliminate code by using a loop to get your two strings. I would have written it like so to get the same result, with the COPY command fixed with quotes:
#echo off
for %%A in (xx app) do (
for /r "c:\test\" %%F in (*%%A*.*) do (
echo Found file - %%F
copy "%%F" "c:\testf\%%A\"
echo Filepath is %%~dpF
echo %%~nxF >>c:\output.log
echo full is %%F
)
)
echo "All Done"
Please note that copying the same file name from multiple source directories into one target directory will result in only one file - last one copied wins.
You can use FIND to test your files :
#echo off&cls
for %%a in (xx app) do call:Treat %%a
exit /b
:Treat
echo Treating : [%1]
for /f "delims=" %%a in ('dir/a-d/b/s ^| find "%1"') do echo copy "%%a" "c:\test\%1"
I put an echo before the copy that you can test the output.

batch: get last folder name from path from txt

i need take paths from txt and get last folder name and then use it.
setlocal EnableDelayedExpansion
set InputFile=somar.txt
for /f "tokens=* delims=" %%x in ('Type "%InputFile%"') do (
set path=%%x
:shift
for /f "tokens=1* delims=\/" %%i in ( "!path!" ) do (
set folder=%%i
set path=%%j
)
if not [!path!] == [] goto :shift
echo folder: !folder!
)
endlocal
problem is that it works only for first line in txt. where is the problem?
You have a number of problems:
1) Your FOR loop is broken the moment you issue a GOTO. You will not get any more FOR loop iterations after GOTO. You could fix this by moving your GOTO loop into a subroutine and then CALL the subroutine from within your DO loop.
2) The PATH environment variable has a reserved meaning for Windows. You should never use that variable name for your own purposes, even if it is localized as you have it. It isn't worth tempting fate. Simply use a different variable name.
3) Perhaps not an issue with your data, but ! is a valid character for a file or folder name. Your expansion of FOR variables will corrupt names containing ! if delayed expansion is enabled. This can be fixed by toggling delayed expansion on and off as needed.
You also have a minor inefficiency - There is no need to use TYPE with your FOR loop. You can simply let FOR read the file directly. (unless the file is unicode)
You could take all the recommendations above, but there is a much simpler solution :-)
EDIT - change made to handle a path that ends with \
#echo off
set "InputFile=somar.txt"
for /f "usebackq eol=: delims=" %%A in ("%inputFile%") do (
for %%F in ("%%A\.") do echo folder: %%~nxF
)
The ~nx FOR variable modifiers directly give you the name and extension of the end of the path. Type HELP FOR from the command line to read about all the modifiers that are available to FOR variables.
For variable filenames:
#Echo OFF
:: By Elektro H#cker
set "File=File.ext"
Call :Get_paths "%InputFile%"
Pause&exit
:Get_paths
Set "AbsolutePath=%~dp1"
set "AbsolutePath=%AbsolutePath:\= %"
FOR %%# in (%AbsolutePath%) do (
Set "LastFolder=%%#"
Echo Folder: %%#
)
Echo Last Folder: %LastFolder%
GOTO:EOF
Output:
Folder: C:
Folder: Users
Folder: Administrador
Folder: Desktop
Last Folder: Desktop
For files:
#Echo OFF
:: By Elektro H#cker
set "File=test.txt"
For /F "Tokens=* usebackq" %%# in ("%FILE%") DO (
Set "AbsolutePath=%%~dp#"
Call set "AbsolutePath=%%AbsolutePath:\= %%"
CMD /Q /C "#FOR %%# in (%%AbsolutePath%%) do (Echo Folder: %%#)"
)
Pause&Exit
InputFile content must contains filename or folder.
ex)
D:\Test1 <= folder
D:\Test2\file.txt <= file
D:\Test3\01. folder <= folder but recognize file. that contain extension.
My code is:
SETLOCAL EnableDelayedExpansion
SET lastFolder=
SET InputFile=somar.txt
FOR /F %%F IN (%InputFile%) DO (
CALL :__GetFolderName "%%F"
#ECHO lastFolder: !lastFolder!
)
GOTO :EOF
:: ******************** Inner Batch
:__GetFolderName
IF "%~x1"=="" SET lastFolder=%~n1 & GOTO :EOF
SET dp=%~dp1
CALL :__GetFolderName "%dp:~0,-1%"
GOTO :EOF
:: ********************
ENDLOCAL
Result is:
lastFolder: Test1
lastFolder: Test2
lastFolder: Test3

Resources