Batch File Move with Partial File Name to Partial Folder Name String - batch-file

I have a directory full of folders that are named in this manner:
ABC-L2-0001__2ABC12345-0101_xxxx
I need to move a lot of files that are named in this manner to the folder that matches the first 9 characters of the files:
2ABC12345-0101.xyxyxyx.yxyxyxyxy.model
Here's what I'm trying based on reading some older posts of similar requests and it isn't working for me.
:start
#echo off
setlocal enableDelayedExpansion
for /f "tokens=*" %%f in ('dir *.model /b') do (
set filename=%%f
set folder8=!filename:~13,9!
set "targetfolder="
for /f %%l in ('dir "!folder8!"*.* /a:d /b') do (
set targetfolder=%%l
)
if defined targetfolder move "!filename!" "!targetfolder!"
)
:end
Any help would be greatly appreciated.

You exchanged the positions of fileName and folderName. You don't take the first 8 characters from file name, but characters 13,9, and you don't look for these characters at middle of the folder name, but at the beginning. Check this fixed code:
:start
#echo off
setlocal enableDelayedExpansion
for /f "tokens=*" %%f in ('dir *.model /b') do (
set filename=%%f
set folder8=!filename:~0,9!
set "targetfolder="
for /f %%l in ('dir "?????????????!folder8!*" /a:d /b') do (
set targetfolder=%%l
)
if defined targetfolder move "!filename!" "!targetfolder!"
)
:end
You also should know that for and for /D plain commands are more efficient than for /F combined with dir /B command.
:start
#echo off
setlocal enableDelayedExpansion
for %%f in (*.model) do (
set filename=%%f
set folder9=!filename:~0,9!
set "targetfolder="
for /D %%l in ("?????????????!folder9!*") do (
set targetfolder=%%l
)
if defined targetfolder move "!filename!" "!targetfolder!"
)
:end

Related

Batch Script merging PDF's with pdftk

Thanks in advance for any help given.
After searching through all relative threads and google search I'm stumped on finding a solution to output a variable name for merging two PDF's.
So I have 100's of PDF's I need to combine (two at a time) in a folder c:/test
The files are set out like below
Company Name Invoice No 123456
Company Name Invoice No 123456 details
Now I have managed to move two files at a time to a different folder and merge them but can't seem to get the desrired output name I'm after which is to put a week ending date in front (or at the end, not fussed) of the first merged filename. Below is the code I have thus far which works but the output file name is blank but gets created.
Very new to batch scripting and would appreciate any help :)
#echo off
setlocal enableextensions enabledelayedexpansion
set pdftk=C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe
set Source=C:\test
set Target=C:\test\test2
set num=2
set filenumber=1
for /F "tokens=1,2 delims=:" %%f in ('dir /b /a-d "%source%\*.pdf" ^| findstr /n "^" ') do (
if %%f leq %num% (
copy "%source%\%%g" "%target%" /y > nul
) else goto endCopy
)
:endCopy
endlocal
for /F "tokens=1,2 delims=:" %%f in ('dir /b /a-d "%target%\*.pdf" ^| findstr /n "^" ') do (
if %%f leq %filenumber% ( set file=%%~nA
)
)
pdftk *.pdf cat output we_19_9_2017_%file%.pdf
In endCopy you are trying to get the name of A whereas you are iterating with f. Use set file=%%~nf to set the name of file or set file=%%~ng for second file.
And move endlocal at the end to expand !file! at the end of script like this (note the !):
:endCopy
set "cmd=dir /b /a-d "%target%\*.pdf" ^| findstr /n "^""
for /F "tokens=1,2 delims=:" %%f in ('%cmd%') do if %%f leq %filenumber% set file=%%~nf
pdftk *.pdf cat output we_19_9_2017_!file!.pdf
endlocal
Read more about DelayedExpansion at: https://ss64.com/nt/delayedexpansion.html
The last command doesn't use the target folder for the input files and thus looks for the input files in the current folder, so either include the path or first change to the target path.
Also you set a path-variable for pdftk but don't use it.
If this path isn't included in the %path% it can't be find.
Try this (untested)
#echo off
setlocal enableextensions enabledelayedexpansion
set "pdftk=C:\Program Files (x86)\PDFtk Server\bin\pdftk.exe"
set "Source=C:\test"
set "Target=C:\test\test2"
set num=2
set filenumber=1
for /F "tokens=1,2 delims=:" %%f in (
'dir /b /a-d "%source%\*.pdf" ^| findstr /n "^" '
) do if %%f leq %num% (
copy "%source%\%%g" "%target%" /y > nul
) else goto endCopy
:endCopy
endlocal
for /F "tokens=1,2 delims=:" %%f in (
'dir /b /a-d "%target%\*.pdf" ^|findstr /n "^" '
) do if %%f leq %filenumber% set file=%%~nf
PushD "%Target%"
"%pdftk%" *.pdf cat output we_19_9_2017_%file%.pdf
PopD

batch file remove X characters of filename

I did batch file which copy 3 files and need to rename it by removing last 33 characters. The copy works fine but removing last 33 characters not... I saw more then one answer on web and try it all but nothing work so far.
My batch file look like this:
for /f "delims=" %%i in ("my folder") do (
ren "%%i" "%i:~0,-33%".txt
)
I tried already:
set fName=%%i
ren "%fName%" "%fName:~0,-33%.txt"
From the information I got here, try this:
#echo off
setlocal enabledelayedexpansion
set "folderpath=[Your Folder Here...]"
cd %folderpath%
for /f %%a in ('dir /b "*.txt"') do (
set "fname=%%~na"
ren "%%a" "!fname:~0,-33!.txt"
)
endlocal
This is similar to the answer above. You should make sure the batch file is OUTSIDE the folder.
EDIT.
When dealing with variables formed inside FOR and IF's, use delayed expansion (i.e. !var!, instead of %var%). Anyway, this is the fixed code:
#echo off
setlocal enabledelayedexpansion
::NO Last Backslash...
set "sourcepath=C:\Users\tzahi.k\Desktop\testSource\source2"
set "folderpath=C:\Users\tzahi.k\Desktop\testSource\des"
for /F "delims=" %%a in ('dir /b /od "%sourcepath%\*.txt"') do (
set "youngest=%%a"
xcopy /y "%sourcepath%\!youngest!" "%folderpath%"
)
cd /d %folderpath%
for /f %%a in ('dir /b "*.txt"') do (
set "fname=%%~na"
ren "%%a" "!fname:~0,-33!.txt"
)
endlocal
pause
Here's the batch file you'd want to run:
#echo off
Setlocal EnableDelayedExpansion
#for /f "delims=" %%i in ('dir /b *.txt') do (
set fname=%%~ni
set fname=!fname:~0,-33!.txt
ren "%%i" "!fname!"
)
endlocal
This should work
#echo off
setlocal enabledelayedexpansion
set FOLDER_PATH=C:\Some\Path\
for %%f in (%FOLDER_PATH%*) do if %%f neq %~nx0 (
set "filename=%%~nf"
ren "%%f" "!filename:~0,-33!%%~xf"
)
PAUSE
Or better this
#echo off & setLocal enableDELAYedeXpansion
for /f "tokens=* delims= " %%a in ('dir /b *.txt') do (
set F=%%~Na
set F=!F:~0,33!
move /y "%%a" "!F!%%~Xa"
)

How to rename all subfolders in a folder depending on name of first subfolder within each folder to rename?

#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "tokens=1* delims=" %%a IN (
'dir /b /ad "%sourcedir%\*" '
) DO (
ECHO "%sourcedir%.%%a\%%a\"
)
GOTO :EOF
I want to edit this batch file slightly. I have the following path structure:
source\folders\versions
Each folder underneath source has one "versions" folder.
For example:
source\component1\3.2\
source\component2\1.3\
source\component3\4.2\
needs to be changed to:
source\component1.3.2\3.2\
source\component2.1.3\1.3\
source\component3.4.2\4.2\
What must be edited in batch code to get this folder structure from above?
Here is a batch code to rename each subfolder in a specified folder by appending a dot and the name of first found subfolder of each subfolder to rename.
#echo off
set "SourceDir=U:\sourcedir"
cd /D %SourceDir%
for /f "usebackq delims=" %%a in ( `dir "%SourceDir%\*" /ad /b 2^>nul` ) do (
for /f "usebackq delims=" %%b in ( `dir "%%a\*" /ad /b 2^>nul`) do (
ren "%%a" "%%a.%%b" 2>nul
)
)

compare file content in folder using windows batch

I've been struggling with this for several days... there is one folder with a lot txt files with random names that are generated from server timestamps, but content of files must not be identical for two files in that folder! any ideas? my only option is using windows batch
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
PUSHD "%sourcedir%"
FOR %%a IN (*.*) DO (
FOR %%c IN (*.*) DO IF /i "%%~nxa" lss "%%~nxc" IF "%%~za"=="%%~zc" (
FC "%%a" "%%c" >NUL
IF NOT ERRORLEVEL 1 ECHO "%%a" and "%%c" are identical
)
)
GOTO :EOF
You would need to change the setting of sourcedir and of the filemask *.* to suit your circumstances.
Revision for only-one-mention-of-a-duplicate-file
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
PUSHD "%sourcedir%"
FOR %%a IN (*.*) DO (
SET "reported="
FOR %%c IN (*.*) DO IF NOT DEFINED reported IF /i "%%~nxa" lss "%%~nxc" IF "%%~za"=="%%~zc" (
FC /b "%%a" "%%c" >NUL
IF NOT ERRORLEVEL 1 ECHO "%%a" and "%%c" are identical&SET reported=Y
)
)
GOTO :EOF
I've also added /b to fc to allow for non-text files.
The solution below process the list of file names just once, so it should run faster.
#echo off
setlocal EnableDelayedExpansion
for %%a in (*.txt) do (
if not defined size[%%~Za] (
set size[%%~Za]="%%a"
) else (
set newName="%%a"
for %%b in (!size[%%~Za]!) do (
fc "%%a" %%b >NUL
if not errorlevel 1 (
echo "%%a" and %%b are identical
set "newName="
)
)
if defined newName set "size[%%~Za]=!size[%%~Za]! !newName!"
)
)
If two files are identical, the name of the second one is not saved in the lists, so it is not compared again vs. other same size files. If no more than two files may be identical, then this method could be modified so the name of the first file be also removed from the lists (below the echo ... are identical command), so the method be even faster.
If you may download a third party program that calculate the MD5 checksum, then it may be used to check if two files are identical instead of fc command as foxidrive suggested. This would be faster because the MD5 checksum of each file would be calculated just once and stored in another array (with the file name as index).
As this code uses certutil, this will work only for windows Vista or later versions of the OS. This will check for duplicates in files of the same size and will only read each involved file only once.
#echo off
rem Configure environment
setlocal enableextensions disabledelayedexpansion
rem Where to search for files
set "folder=%cd%"
rem We need a temporary file to hold the size sorted list of files
set "tempFile=%temp%\%~nx0.%random%%random%%random%.tmp"
rem Change to target folder and work from here
pushd "%folder%"
rem Retrieve the list of files with its size and set a environment variable
rem named as the size of the file. The value of this variable will hold the
rem number of files with this size
(for /f "delims=" %%a in ('dir /a-d /b /os *') do (
echo \%%~za\%%a\
set /a "sz_%%~za+=1"
)) >"%tempFile%"
rem Retrieve the list of sizes that happens more than one time
for /f "tokens=2,3 delims=_=" %%a in ('set sz_') do if %%b gtr 1 if %%a gtr 0 (
rem Retrive the list of files with the indicated size
setlocal
for /f "tokens=1,2 delims=\" %%c in ('findstr /l /b /c:"\%%a\\" "%tempFile%"') do (
set "hash="
for /f "skip=1 delims=" %%e in ('certutil -hashfile "%%d"') do if not defined hash (
rem For each file, compute its hash. This hash is used as a variable name.
rem If the variable is defined, a previous file has the same size and hash
rem so it is a duplicate
set "hash=1"
if defined "%%e" (
<nul set /p ".=%%d = "
setlocal enabledelayedexpansion
echo(!"%%e"!
endlocal
) else (
rem Store the name of the file in a variable named as the hash of the file
set ""%%e"=%%d"
)
)
)
endlocal
rem This inner setlocal/endlocal ensures there is no collision between hashes for
rem files with different sizes
)
rem Cleanup
popd
del /q "%tempFile%" >nul 2>nul
endlocal
edited For a simplified version with no temporary file (the list is created in memory) while still reading only the needed files only once each file, AND as demanded a more readable output
edited again to correct a problem with the output of different groups of duplicated for the same file size
#echo off
setlocal enableextensions disabledelayedexpansion
set "folder=%~1"
if not defined folder set "folder=%cd%"
pushd "%folder%"
for /f "delims=" %%a in ('dir /a-d /b /os *') do (
set /a "sz_%%~za+=1"
setlocal enabledelayedexpansion
for /f "delims=" %%b in ("!fl_%%~za! ") do (endlocal & set "fl_%%~za=%%b "%%a"")
)
for /f "tokens=2,3 delims=_=" %%a in ('set sz_') do if %%b gtr 1 (
setlocal & setlocal enabledelayedexpansion
for /f "delims=" %%c in ("!fl_%%a!") do (
endlocal
for %%d in (%%~c) do (
if %%a equ 0 ( set "hash=0" ) else (
set "hash="
for /f "skip=1 delims=" %%e in ('certutil -hashfile "%%~d"') do if not defined hash set "hash=%%e"
)
setlocal enabledelayedexpansion
for /f "delims=" %%e in ("!hash!") do if defined hash_"%%~e" (
for /f "delims=" %%z in ("!hash_"%%~e"!") do (endlocal & set "hash_"%%~e"=%%z"%%~d";")
) else (
endlocal & set "hash_"%%~e"="%%~d"="
)
)
)
for /f "tokens=1,* delims==" %%c in ('set hash_ 2^>nul^|find ";"') do (
set "first=1"
for %%e in (%%d) do if defined first (set "first=" & echo(%%e) else (echo( = %%e)
)
endlocal
)
popd
endlocal
exit /b

Partial path known..need to search for file type inside

There is a particular folder that begins with a name such as SS followed by random characters. The names would be different every time and the only thing we are sure of is the folder begins with SS. How do we look if this folder has a .txt file inside in batch programming.
An idea :
#echo off
for /f "delims=" %%a in ('dir /b/ad ^|find /i "SS"') do set $Dir=%%a
dir /b/a-d *.txt %$dir%>nul
if %errorlevel% equ 0 echo File(s) found in "%$DIR%"
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\ss*" 2^>nul'
) DO (
FOR /f "delims=" %%h IN (
'dir /b /a-d "%sourcedir%\%%a\*.txt" 2^>nul'
) DO (
ECHO "%sourcedir%\%%a\%%h"
)
)
GOTO :EOF
should solve your problem - you need to change sourcedir to suit your system, obviously.
The code below check if the folder contain any .txt file:
#echo off
set "filePath="
for /D %%a in (SS*) do if exist "%%a\*.txt" do set "filePath=%%a"
if defined filePath echo File exists in folder %filePath%
If you want to check for a particular .txt file, just change *.txt by the appropriate name.

Resources