i have a batch script which i use to merge all the same name txt files from directories & subdirectories into one, here's my code:
#echo off
for /f "tokens=*" %%a in (textfilenames.txt) do (
for /D /R %%I in (%%a.txt) do (
type "%%I" >> merged.tmp
echo. >> merged.tmp
)
ren merged.tmp All_Combined_%%a.txt
)
)
#pause
and so when the loop doesn't finds the file on some directories then this msg is displayed:
The system cannot find the file specified.
The system cannot find the file specified.
The system cannot find the file specified.
Press any key to continue . . .
and i wanna hide above error and so i used >NUL in file name eg:
#echo off
for /f "tokens=*" %%a in (textfilenames.txt) do (
for /D /R %%I in ('%%a.txt^>NUL') do (
type "%%I" >> merged.tmp
echo. >> merged.tmp
)
ren merged.tmp All_Combined_%%a.txt
)
)
#pause
but i'm still getting error msg, i want to make this script completely silent like no error nothing or if somehow it's not possible then i wann customize the error to something like:
The system cannot find the example.txt specified. in the \Subfolder\Enigma\
etc!
If you do it right, you do not need to hide anything.
In this example we use the dir command with the /s function to search for files. It will not complain about files not found because it does not expect the file exist indefinitely in any given directory, it simply searches for it:
#echo off
for /f "useback delims=" %%a in ("textfilenames.txt") do (
for /f "delims=" %%I in ('dir /b/s/a-d "%%a.txt"') do (
(type "%%I"
echo()>>All_Combined_%%a.txt
)
)
)
#pause
Note, I eliminated the ren part as that is not needed. You can write to the combined file in the loop.
I also use echo( instead of echo. for reasons that can be found on numerous answers in SO.
Lastly, we can eliminate one parenthesized code block, by putting the second for loop inline with the first:
#echo off
for /f "useback delims=" %%a in ("textfilenames.txt") do for /f "delims=" %%I in ('dir /b/s/a-d "%%a.txt"') do (
(type "%%I"
echo()>>All_Combined_%%a.txt
)
)
#pause
Related
I have went through a lot of guides for it, but havent found a way to do something similar to lets say turn all files in folder, like these files:
djhwu4s_cat_ruhg29.png
397y_dog_j0929_ej93.png
8yhh_owl.png
into these:
_cat.png
_dog.png
_owl.png
So basically removing everything from file names but a list of predefined strings i am searching for. In example above i would define list as "_cat", "_dog", "_owl". I know that each file will have only one of these variables, and there will be only one file with each of them in folder.
Will appreciate any tips on how to achieve that. Thanks in advance!
edit:
Here is what i came up with (with stuff i can understund) and what seems to be working fine now.
#echo off
setlocal enabledelayedexpansion
set v1=_cat-cat
set v2=_cat-owl
set v3=_cat
set v4=_dog
set v5=_owl
set v6=_horse
FOR /L %%a IN (1,1,6) DO (
rem echo %%a
rem echo !v%%a!
FOR /f %%f in ('dir /b /a:-D *!v%%a!.*') DO (
REN %%f !v%%a!.*
)
FOR /f %%f in ('dir /b /a:-D *!v%%a!_*.*') DO (
REN %%f !v%%a!.*
)
)
rem using two passes of this simpler code i can grasp and understund with dot and with underscore
rem after constructed variables value i make sure cat-cat is not recognised as and renamed to cat
rem no matter if im getting file with that variable as the last string before extension or another underscore
rem Gonna test it in combat now
For some reason this stuff doesnt work with files containing spaces and characters like:
"ab’c efg_dog.png"
FOR /L %%a IN (1,1,36) DO (
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
REN "%%f" "!v%%a!.*"
)
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
REN "%%f" "!v%%a!.*"
)
)
After further testing i have realised the problem starts with the %%f, and not the REN function as i thought. echo %%f before ren gives just the first part of the name to the first space, hence the REN function cant find the file. In case of "ab’c efg_dog.png" after finding the file with dir, the %%f becomes just "ab’c".
edit: After more tests and experiments and adding those "delims" to the code, the echo now shows proper, full names to be renamed, but it replaces that weird ’ character with ' for the REN command and thats why it still cant find the file to rename.
FOR /L %%a IN (1,1,36) DO (
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
)
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"
FOR /f "delims=" %%e IN ('dir /b /a-d "*_*" 2^nul ^|findstr /v /b "_"') DO (
FOR /f "tokens=2delims=_." %%y IN ("%%e") DO ECHO REN "%%e" "_%%y%%~xe"
)
POPD
GOTO :EOF
For lack of examples, here's a start.
Always verify against a test directory before applying to real data.
Process the list of filenames that match *_*; find those names that do not start _, pick the second string between the delimiters _ and . and rename using that string (in %%y), prefixed by _ and appended with the original extension.
The ren command is simply echoed to the screen for verification. When happy, remove the echo before the ren to actually execute the rename.
I am trying to write a batch script that recursively lists all directories and their files with *.js type in the below format:
For example, if I start with the C:\project directory
c:\project
project.js
project_time.js
c:\project\core
core.js
core_render.js
core_application.js
I tried to implement the above logic in code as follows:
#echo off
for /r %%f in (*.js) do (
echo %%f >> names.txt
)
pause
I was not able to print the directory under which the files are listed.
#echo off
setlocal disabledelayedexpansion
set "lastdir="
( for /r %%A in (*.js) do (
set "nextdir=%%~dpA"
setlocal enabledelayedexpansion
if /i not "!lastdir!" == "!nextdir!" (
rem Empty line and directory path.
if defined lastdir #echo(
#echo !nextdir!
)
endlocal
rem Filename.
#echo %%~nxA
set "lastdir=%%~dpA"
)
) > "names.txt"
The lastdir variable is to record the last directory path so it is echoed only once.
If lastdir is different to %%~dpA:
If lastdir is defined, then an empty line will be echoed.
Directory path of found file is echoed.
Filename is always echoed.
for modifiers dp is the drive and path. nx is the name and extension.
setlocal enabledelayedexpansion is used only where needed so paths with ! are not vulnerable.
I am not going to suggest a command line solution as it would be very long. Instead suggest use of tree command if the output format is suitable.
Here's an untested example, (I'm not expecting it to be quick if your base directory is large):
#Echo Off
(
For /F "Delims=" %%G In ('Dir /B /S /A:D "C:\Project" 2^> NUL') Do (
%__AppDir__%where.exe /Q "%%G":*.js 1> NUL 2> NUL
If Not ErrorLevel 1 (
Echo/
Echo %%G
For /F "EOL=| Delims=" %%H In ('%__AppDir__%where.exe "%%G":*.js')Do (
Echo %%~nxH
)
)
)
) 1> "names.txt"
Pause
If you prefer to run something from the Command Prompt, then try this version:
(For /F "Delims=" %G In ('Dir /B/S/AD "C:\Project" 2^>NUL')Do #(%__AppDir__%where.exe /Q "%G":*.js >NUL 2>&1&&(Echo/&Echo %G&For /F "EOL=|Delims=" %H In ('%__AppDir__%where.exe "%G":*.js')Do #Echo %~nxH)))>"names.txt"
Two simple ways to do this:
dir /S *.js
You get the answers, just as you requested.
FORFILES /S /M *.js /C "cmd /c echo #path"
You get complete path for every file.
I have a folder full of text files that I need to split based on the (optional) presence of a delimiter. I found an answer for how to actually split the file here: Split text file into 2 files by separator
#echo off&setlocal
set "file=_frmCore.frm"
for /f "delims=[]" %%i in ('^<"%file%" find /n "SearchTermHere"') do set "split=%%i"
(for /f "tokens=1*delims=[]" %%i in ('^<"%file%" find /n /v ""') do if %%i lss %split% echo(%%j)>"%file%.new1"
<"%file%">"%file%.new2" more +%split%
type "%file%.new?"
Works great for what it is, but I need a few refinements and not sure where to start. Looking for:
Wrap it in a loop for all files in the directory (no subfolders to worry about)
"SearchTermHere" is the first on a line (the only on a line), with a specific term on the previous line that I'd rather match for safety... how can I tell it "PreviousLine/r/nSearchTermHere/r/n"? Unsure of the correct syntax here.
Rather than creating two new files, move the "after search term" portion to a new file and remove it from the original
Parameterize folder name to operate in so I can call from other programs
(apologies... I've tried deciphering this code and finding out what does what and trying to go from there, but this stuff is not my cup of tea and a strong push in the right direction would be wonderful)
#ECHO OFF >NUL
SETLOCAL enableextensions
rem enabledelayedexpansion
set "_files=*.frm"
set "_sfind=SearchTermHere"
if not "%~1"=="" if exist "%~1\" (
pushd "%~1"
set "_popd=popd"
) else ( set "_popd=" )
for /F "delims=" %%G in ('findstr /m "^%_sfind%$" %_files%') do (
type NUL > "%%G.new1"
type NUL > "%%G.new2"
for /f "delims=:" %%i in ('findstr /n "^%_sfind%$" "%%G"') do (
for /f "tokens=1* delims=:" %%I in ('findstr /n "^" "%%G"') do (
if %%I lss %%i (
>> "%%G.new1" echo(%%J
)
if %%I gtr %%i (
>> "%%G.new2" echo(%%J
)
)
)
rem remove `ECHO` from next line no sooner than debugged!
ECHO move /Y "%%G.new1" "%%G"
type "%%G.new?"
)
%_popd%
Changes made in your code:
Wrap it in a loop for all files in the directory: see for /F "delims=" %%G loop against all files matching your criteria: findstr /m "^%_sfind%$" %_files%.
"SearchTermHere" is the first on a line (the only on a line): ^=beginning of line and $=end of line in findstr /m "^%_sfind%$" %_files%; used findstr command rather than find.
Rather than creating two new files, move the "after search term" portion to a new file and remove it from the original: see the move /Y "%%G.new1" "%%G" workaround. Operational move command is ECHOed here merely for debugging purposes. Remove ECHO from that line no sooner than debugged!
Parameterize folder name to operate in so I can call from other programs:
call "batch path\31749577.bat" "folder path"
see %~1 test: if a parameter is supplied to the batch and represents a folder, (more in Command Line arguments (Parameters)) and
see pushd - popd pair: PUSHD changes the current directory/folder and store the previous folder/path for use by the POPD command.
The tricky <"%%G">"%%G.new2" more +%%i command substituted with less effective but clear to understand if %%I gtr %%i ( ... inside the %%I loop. However, next code snippet (entire %%G loop) will work as well:
for /F "delims=" %%G in ('findstr /m "^%_sfind%$" %_files%') do (
for /f "delims=:" %%i in ('findstr /n "^%_sfind%$" "%%G"') do (
>"%%G.new1" (for /f "tokens=1* delims=:" %%I in ('
findstr /n "^" "%%G"') do if %%I lss %%i echo(%%J)
<"%%G">"%%G.new2" more +%%i
)
rem remove `ECHO` from next line no sooner than debugged!
ECHO move /Y "%%G.new1" "%%G"
type "%%G.new?"
)
Excuse me. Although your description is extensive, it is also confusing. The Batch file below:
Search for a line that is "SearchTermHere".
If the previous line is "PreviousLine":
Move from line after SearchTerm up to end of file to another file
Repeat previous process on all files in folder.
.
#echo off
setlocal EnableDelayedExpansion
set "find=SearchTermHere"
set "prevLine=PreviousLine"
rem Process the folder given in parameter
cd %1
rem Process all files in folder
for /F "delims=" %%F in ('dir /A-D /B') do (
rem Get the line number of the search line - 1
set "numLines="
for /F "delims=:" %%a in ('findstr /N "^%find%$" "%%F"') do set /A "numLines=%%a-1"
if defined numLines (
rem Open a code block to read-input-file/create-output-file
< "%%F" (
rem Copy numLines-1 lines
for /L %%i in (1,1,%numLines%) do (
set "line="
set /P "line="
echo(!line!
)
rem If the line before search is prevLine
if "!line!" equ "%prevLine%" (
rem Copy just the search line to original file
set /P "line="
echo !line!
rem and copy the rest of lines to another file
findstr "^" > "%%~nF-PART2%%~xF"
)
) > "%%F.tmp"
if exist "%%~nF-PART2%%~xF" (
rem Replace original file with created output file (first part)
move /Y "%%F.tmp" "%%F" > NUL
) else (
rem Remove the output file
del "%%F.tmp"
)
)
)
For a further explanation of this method, see this post.
Sorry, I was unable to use either of the proposed solutions. However they did help - I spent the last two days learning about the (odd) syntaxes and operations involved in batch files and came up with the following. It doesn't do quite everything that I was looking for (and I altered the program that outputs the files a bit for further support), but it does get the job done:
#ECHO off
setlocal EnableDelayedExpansion
:: change the working directory to match the input
cd /D %~d1
cd %~p1\
:: loop all .frm files and find the CodeBehindForm string
for %%F in (*.frm) do (
for /F "delims=[]" %%a in ('^<%%F find /n "CodeBehindForm"') do (
if %%a gtr 0 (
for /F "tokens=1*delims=[]" %%i in ('^<"%%F" find /n /v ""') do if %%i gtr %%a echo(%%j)>>"%%~nF.vb"
for /F "tokens=1*delims=[]" %%i in ('^<"%%F" find /n /v ""') do if %%i lss %%a echo(%%j)>>"%%~nF.fwm"
:: if the codebehind was found and parsed out, there's a .fwm and .vb file
:: remove the original
if exist %%~nF.vb del %%F
)
)
:: change the .fwm extensions back to their original .frm extensions
ren *.fwm *.frm
I'm sure it's not "correct" in many ways, but for now it gets the job done.
Thanks for the help.
I try to improve an overview of my search and find memories for batch files in Windows XP command prompt environment.
In order to my previous sentence I am not happy with my search possibilities and have to post a question.
I try to compare the names of some text files and have written words in a text file that are by reading the same. With such a start environment I wrote following batch script to get an echo output.
The aim is
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%b in ('dir "C:\A Folder"') do set var=%%~nb & echo !var!
rem The output is the name of the files without extension. Now my question:
rem Is it possible to compare the above file names with some input
rem from a text file, for example like:
for /f "delims=" %%b in ('dir "C:\A Folder"') do set var=%%~nb & for /f %%a in (Textfile.txt) do (if !var!==%%a echo good else echo search)
rem That returns no output. I would like to know if there are possibilities
rem to do that? And if it is possible, how to revise this batch file?
endlocal disabledelayedexpansion
pause
Have a nice day, wishes
Stefan
This should work with Latin characters - some foreign characters may not work:
#echo off
for /f "delims=" %%b in ('dir /b /a-d "C:\A Folder\*.*" ') do find /i "%%~nb" < "textfile.txt" >nul && (echo "%%~nb" found) || (echo "%%~nb" not found)
pause
proper formatting you code increases readabilty:
for /f "delims=" %%b in ('dir /b /a-d "C:\A Folder"') do (
for /f %%a in (textfile.txt) do (
if "%%~nb"=="%%a" ( echo good ) else ( echo search )
)
)
I added a /b to the dircommand (show name only, no date/time/attributes) and a /a-d to exclude directorynames.
You don't need to use a variable (!var!) here (but you can, it works fine).
I need to include page size information of many single-paged pdf's into their filenames. E.g. "150x250mm.pdf". I found no renamer apps able to do it. I suspect this could be done using a batch file and pdfinfo.exe (from xpdf suite), but I have no idea how to make use of it.. Could you give me some hints?
Yes, you can convert from postscript points to MM. In this case, the script is in the top level folder containing the PDF's to be renamed. It does go into subfolders. If you don't want or need that, remove the /s from the dir command on the 5th line. Change the paths as needed.
#echo off
setlocal enabledelayedexpansion
set "pdfi=U:\Scripts\Utilities\xpdf\pdfinfo.exe"
for /f "delims=" %%a in ('dir /b /s *.pdf') do (
for /f "tokens=3,5 delims= " %%b in (
'%pdfi% -meta "%%a"^|find /i "Page size:"') do (
set pts=%%b %%c
for %%d in (!pts!) do (
call :Eval %%d*.352777778 mm
set "mm1=!mm1!x!mm!"
)
ren "%%~dpfnxa" "!mm1:~1!.pdf"
set mm1=
)
)
exit /b
:Eval <in> <out>
setlocal
if exist eval.vbs del eval.vbs
>eval.vbs echo wsh.echo formatnumber(eval("%1"),0)
for /f "delims=" %%a in (
'cscript //nologo eval.vbs'
) do endlocal & set %~2=%%a
del eval.vbs