Loop through folder with files including a space - batch-file

I want to loop through a folder and let run an algorithm on each .tif file found. Unfortunately this does not work for files which have a space character in their name. As my path already contains folders with space, i put the variable which stores the path name in double-quotation marks.
FOR /F %%k IN ('DIR /B "%mypath_import%"*.tif') DO (
SET infile=%%k
SET outfile=!infile:.tif=_UTM.tif!
REM ... do something
This is my attempt so far but it won't work for the files which include a space as well.

You done need all that. You can use the normal for loop without having to use /f
#echo off
setlocal enabledelayedexpansion
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do (
set "infile=%%~i"
echo "!infile:.tif=UTM.tif!"
)
The above will however echo full path to and file name, if you want filename only with extension:
#echo off
setlocal enabledelayedexpansion
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do (
set "infile=%%~nxi"
echo "!infile:.tif=UTM.tif!"
)
or without the need to delayedexpansion
#echo off
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do echo %%~dpni_UTM%%~xi
and again if you require the name and extension only.
#echo off
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do echo %%~ni_UTM%%~xi
EDIT
As per comment from #Stephan, keep in mind if you are doing actual renames and you run the script more than once it will keep on appending _UTM each time. So you'll get filename_UTM_UTM.tif etc. So you can exclude files from the loop by including findstr
for /f "delims=" %%i in ('dir /b *.tif ^|findstr /eiv "_UTM.tif"') do echo %%~ni_UTM%%~xi

Related

Tesseract-OCR to batch files in all subfolders, Windows cmd?

I am trying to use Tesseract-OCR to read and OCR all .png files, not only in current folder, (as there is answer for that) but also in all subfolders.
This works for folder:
for %%A in ("C:\Users\x\AppData\Local\Tesseract-OCR\temp\*.png") do C:\Users\x\AppData\Local\Tesseract-OCR\tesseract.exe "%%~fA" "%%~dpnxA"
I tried with this to go through all subfolders that I have in "temp" folder:
(for /r %%a in (*.png) do C:\Users\x\AppData\Local\Tesseract-OCR\tesseract.exe "%%~nxa" "%%~dpnxA")
but I got this errors for every file:
C:\Users\x\AppData\Local\Tesseract-OCR\temp>C:\Users\x\AppData\Local\Tesseract-OCR\tesseract.exe "01.png" "%~dpnxA"
Tesseract Open Source OCR Engine v4.1.0-elag2019 with Leptonica
Error, cannot read input file 01.png: No such file or directory
Error during processing.
It is obvious that the script finds all files in all of the subfolders, but then it cant read then for some reason?
Also, this script works for one folder, but when I try to use with /r it doesnt go through all subfolders:
:Start
#Echo off
Set _SourcePath=C:\Users\x\AppData\Local\Tesseract-OCR\temp\*.png
Set _OutputPath=C:\Users\x\AppData\Local\Tesseract-OCR\temp\
Set _Tesseract="C:\Users\x\AppData\Local\Tesseract-OCR\tesseract.exe"
:Convert
For %%A in (%_SourcePath%) Do Echo Converting %%A...&%_Tesseract% %%A %_OutputPath%%%~nA
:End
Set "_SourcePath="
Set "_OutputPath="
Set "_Tesseract="
Any ideas?
Perhaps this sort of thing is what you're looking for:
#Echo Off
SetLocal DisableDelayedExpansion
Set "_SourcePath=%LocalAppData%\Tesseract-OCR\temp"
Set "_SourceMask=*.png"
Set "_OutputPath=%LocalAppData%\Tesseract-OCR\temp"
Set "_TesserFile=%LocalAppData%\Tesseract-OCR\tesseract.exe"
For /F "Delims=" %%A In (
'""%__AppDir__%where.exe" /R "%_SourcePath%" "%_SourceMask%" 2>Nul"'
) Do Echo Converting %%A...& "%_TesserFile%" "%%A" "%_OutputPath%\%%~nA"
Note, this assumes that tesseract allows for specifying the output directory and accepts doublequoted strings etc. It also assumes that you intend for all output files to be placed in %_OutputPath%.
If you wanted them to be placed along side their respective .png's then perhaps this will do it:
#Echo Off
SetLocal DisableDelayedExpansion
Set "_SourcePath=%LocalAppData%\Tesseract-OCR\temp"
Set "_SourceMask=*.png"
Set "_TesserFile=%LocalAppData%\Tesseract-OCR\tesseract.exe"
For /F "Delims=" %%A In (
'""%__AppDir__%where.exe" /R "%_SourcePath%" "%_SourceMask%" 2>Nul"'
) Do Echo Converting %%A...& "%_TesserFile%" "%%A" "%%~nA"

Find a file within a for loop in command prompt

I am attempting to find files to run commands against in a command prompt (batch) script. So far, so good:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /R %%I IN ("*.Marker.txt") DO (
SET MARKER=%%I
SET LOG= ???
ECHO MARKER IS !MARKER! AND LOG IS !LOG!
)
Basically, I want to iterate on a pair of files and execute a command on them (for now just echo). The problem I have is that the log file can be in any directory from where the *.Marker.txt file exists. I can't simply just say 100.Marker.log because that's just the filename, not the full path. Some examples:
C:\Temp\Samples\3A5\100.Marker.txt
C:\Temp\Samples\3A5\9\1\100.Marker.log
C:\Temp\Samples\39B\122.Marker.txt
C:\Temp\Samples\39B\2\5\122.Marker.log
So, not really sure what to do here.
You can use PUSHD/POPD to push/pop the working directory during the script and an inner loop.
FOR /R %%I IN ("*.Marker.txt") DO (
SET DIRECTORY=%%~DPI
SET FILENAME=%%~NI
SET MARKER=%%I
PUSHD !DIRECTORY!
FOR /R %%J IN ("!FILENAME!.log") DO (
SET LOGFILE=%%J
ECHO !MARKER!
ECHO !LOGFILE!
)
POPD
)
Not sure how to find a single value, the FOR technically will run on all matches, but if you say you should only have a single value than the inner loop will only run once per marker file. Maybe there's a more efficient way to search for a single file without using FOR?
If all of your files have the same format (text.Marker.ext), then you can use:
#echo off
setlocal EnableDelayedExpansion
for /R %%A IN ("*.Marker.*") DO (
set MARKER=%%A
for /F "tokens=1 delims=." %%B IN ("%%A") do (
set LOG=%%B
)
echo MARKER IS !MARKER! AND LOG IS !LOG!
)
Please note that I don't generally suggest capital letters in batch file.
We make a loop that loops through all subfolders (for /R) trying to find files containing .Marker. (IN ("*.Marker.*")).
We set the output to a variable (MARKER).
Now, we loop through filename found setting delims to .. This means that: token1.token2.token3. . won't be parsed as a token.
Set result to variable.
#echo off
setlocal enabledelayedexpansion
REM following lines to create test environment
md C:\Temp\Samples\3A5\9\1 2>nul
md C:\Temp\Samples\39B\2\5 2>nul
break>C:\Temp\Samples\3A5\100.Marker.txt
break>C:\Temp\Samples\3A5\9\1\100.Marker.log
break>C:\Temp\Samples\39B\122.Marker.txt
break>C:\Temp\Samples\39B\2\5\122.Marker.log
REM end creating test environment
for /R "C:\Temp\Samples\" %%a in ("*.marker.txt") do (
for /f %%b in ('dir /s/b "%%~dpa\%%~na.log"') do (
ECHO Textfile: %%a Logfile: %%b
)
)
The for /R looks recursively for all matching files (*.marker.txt in C:\Temp\Samples\ and subfolders.
The for /f looks for matching log files below the folder, where the marker.txt is.
Output:
Textfile: C:\Temp\Samples\39B\122.Marker.txt Logfile: C:\temp\Samples\39B\2\5\122.Marker.log
Textfile: C:\Temp\Samples\3A5\100.Marker.txt Logfile: C:\temp\Samples\3A5\9\1\100.Marker.log
Note: this assumes, there is only one matching .log for each .txt and it's within the tree below .txt

Batch - Search for part/exact name and copy line from text file into batch as var

This information below is contained in a text file and formatted as such.
/var/www/xxx/html/videos/video_folder_1
/var/www/xxx/html/videos/video_folder_2
/var/www/xxx/html/videos/video_folder_3
/var/www/xxx/html/videos/video_folder_4
/var/www/xxx/html/videos/video_folder_5
/var/www/xxx/html/videos/video_folder_6
/var/www/xxx/html/videos/video_folder_7
I also have a variable called %file_name% in the batch file already defined.
So lets say that is it is %file_name% = V001-video_folder_6.mp4
As you can see there is some more extra information, V001- and .mp4.
I would like to use the var %file_name% to search the text file and return the entire line. In this case it would return /var/www/xxx/html/videos/video_folder_6 and then put this information in a new var, let us say, %folder_path%.
I think I would use findstr however I have been playing around and not getting the best results.
The problem with the methods that use findstr is that they are slow, because they require to execute findstr.exe (a ~30KB file) each time. A simpler/faster solution is to use just internal Batch commands with the aid of an array. If the number of names to process is large, the difference in time between the two methods may be marked.
#echo off
setlocal EnableDelayedExpansion
rem Load the lines from text file into an array with the last part as index:
for /F "delims=" %%a in (test.txt) do (
set "line=%%a"
for %%b in (!line:/^= !) do set "lastPart=%%b"
set "folder[!lastPart!]=%%a"
)
set "file_name=V001-video_folder_6.mp4"
rem Get the folder from file_name:
for /F "tokens=2 delims=-." %%a in ("%file_name%") do set "folder_path=!folder[%%a]!"
echo Folder path is: %folder_path%
Let us assume the posted lines are in file Test.txt in current working directory.
#echo off
set "file_name=V001-video_folder_6.mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto NextCommand
)
:NextCommand
echo Full folder path is: %folder_path%
Open a command prompt window, enter the command for /?, hit key RETURN or ENTER and read output help to understand this little code.
The command goto inside FOR loop results in an immediate exit from loop processing output of findstr.exe after first found line containing the folder path of interest.
Perhaps better in case of searched folder is not found in text file:
#echo off
set "file_name=V01-VIDEOS for school (Miss Patrick).mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto FoundFolder
)
echo "%folder%" not found in file Test.txt.
pause
goto :EOF
:FoundFolder
echo Full folder path is: "%folder_path%"
pause
This should work:
::file_name=V001-video_folder_6.mp4
::file containing folder paths is called paths.txt
for /f "tokens=2 delims=-." %%a in ("%file_name%") do set FN=%%a
for /f %%a in ('findstr /E /L "%FN%" "paths.txt"') do set folder_path=%%a
echo %folder_path%
Which does what you want in effectively two lines.

Rename multiple files in a directory using batch script

I have about 1000 images and they have name like "IMG-12223". I want to rename them to 1 2 3 4 ... 1000. How can I do that. I have written a batch script which list the files but I don't know how to rename each file. e.g. rename first image with name "IMG-12223" to 1 , second image with name "IMG-23441" to 2 and so on ...
for /r %%i in (*) do (
echo %c%
)
Here's the script. Just put the script in your folder and run it.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *') do (
if not "%%~nxi"=="%~nx0" (
ren "%%i" "!a!"
set /a a+=1
)
)
If you want to keep the extensions, i.e. rename "IMG-12223.jpg", "IMG-12224.jpg", etc to "1.jpg", "2.jpg", etc, you may use the following script.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *.jpg') do (
ren "%%i" "!a!.jpg"
set /a a+=1
)
[Update] Here're explanations for the lines mentioned in Jack's comment.
setlocal EnableDelayedExpansion
In general, we want the variable a to be delayed expansion when it's executed but not the line is read. Without it, the variable a cannot get its increased value but always 1.
For the detail of EnableDelayedExpansion, please refer to the answer https://stackoverflow.com/a/18464353/2749114.
for /f "delims=" %%i in ('dir /b *.jpg')
Here dir with /b option, lists only file names of all jpg files.
The for loop traverses and renames all jpg files.
For the delims option, since the default delimiter character is a space, without the option delims=, it fails with the image files with spaces in the file names. I.E. for an image file named "img with spaces.jpg", without the option, the value of %%i is "img" but not the whole name "img with spaces.jpg", which is incorrect.
For for loop, please refer to the page http://ss64.com/nt/for_f.html.
if not "%%~ni"=="%~n0"
I have change it to if not "%%~nxi"=="%~nx0" to be more accurate. And the codes attached have been updated.
It's actually used to avoid to rename the bat file itself. If we limit the renaming only upon "jpg" files, then the line is not needed.
%%~nxi is the file name with extension for each file traversed. And %~nx0 is the running bat file with extension. For details, please refer to the page DOS BAT file equivalent to Unix basename command?.
There is no need for a batch script. A simple one liner from the command line can do the job :-)
I use DIR /B to generate the list of files, piped to FINDSTR to number the files, all enclosed withn FOR /F to parse the result and perform the rename.
for /f "delims=: tokens=1*" %A in ('dir /b *.jpg^|findstr /n "^"') do #ren "%B" "%A%~xB"
Double the percents if you want to put the command in a batch script.
Try this, you have pair of namevalues in a text file then loop values and do the magic. Namevalues are separated by empty spaces. This allows you to map old->new filenames accordingly. Or you keep idx+1 counter and use it for new filenames.
keyvalue.bat
#echo off
set idx=0
for /F "tokens=1,2" %%A in (keyvalue.txt) do call :PROCESS "%%A" "%%B"
GOTO :END
:PROCESS
set var1=%~1
set var2=%~2
set /A idx=%idx%+1
echo %var1% goes to %var2% (%idx%)
GOTO :EOF
:END
pause
keyvalue.txt
file888.dat newfile1.dat
file333.dat newfile2.dat
file9.dat newfile3.dat
file01.dat newfile4.dat

Batch: Rename multiple files using input string

I am trying to rename files after the user inputs a string they want to remove from the file name. This works fine except when I want to rename files that are in a different location than the script:
Here is what i have so far which works if I dont specific the file path (e.g. remove C:\DATABASE\*.* /s)
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir C:\DATABASE\*.* /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Thanks!
Use this instead. e.g.:
remove *.*
or
remove "relative path\*.*"
or
remove C:\DATABASE\*.*
or
remove "C:\My Database\2010-*.bak"
Meaning that a directory and file mask must be specified. Here's the remove.bat file:
#echo off
setlocal enabledelayedexpansion
set mask=%~1
set mask=!mask:%~dp1=!
if not exist "%~1" (
echo No files found
goto :eof
)
pushd "%~dp1"
SET /P X=Type in the String that you want to remove and then press ENTER:
set deletestring=%X%
for /f "delims==" %%F in ('dir "%mask%" /s /b ^| find "%deletestring%"') do (
set oldfilename=%%F
set newfilename=!oldfilename:%deletestring%=!
Ren "!oldfilename!" "!newfilename!"
)
Your primary problem you are running into is that the 1st argument to REN can accept full path info, but the 2nd can only contain the new name without path info. You can use the ~nx modifier to extract the name and extension from the full path reported by the FOR /F command.
Your FOR /F options are not reliable - it will break if the file name contains =. You want to set delims to nothing instead.
This problem is actually more complicated than it first looks. Your code will attempt to rename both files and directories. If you want to rename the directories then you must rename in reverse alpha order because the entire list is built before any thing is renamed. If you process in normal alpha order and rename a directory, then subsequent entries within that directory will not be found.
The FIND filter in the IN() clause is not necessary. Ideally your filter should only match the file or directory name, not the path. That is doable, but a bit tricky. I would simply skip the filtering in the IN() clause and do it in the DO clause.
A file or directory name can contain ! character. But the FOR variable expansion will be corrupted if it contains ! and delayed expansion is enabled. The problem can be avoided by toggling delayed expansion on and off within the loop.
It is possible for the entire name to be removed by the search and replace, but you cannot rename a file to nothing. So I added a test to ensure there is a name left.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b ^| sort /r') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)
If you don't really want to rename directories then you need to add the /A-D option. I first thought you could use a FOR /R statement, but that could potentially cause the same file to be renamed twice. FOR /F buffers the entire result set before processing any files, but FOR /R does not.
setlocal disableDelayedExpansion
SET /P "X=Type in the String that you want to remove and then press ENTER:"
for /f "delims=" %%F in ('dir C:\DATABASE\* /s /b /a-d') do (
set "old=%%F"
set "file=%%~nxF"
setlocal enableDelayedExpansion
set "new=!file:%X%=!"
if defined new if !new! neq !file! ren "!old!" "!new!"
endlocal
)

Resources