I'm writing to you because I need to create a batch file that allows me to rename many files in .pdf keeping only the first 50 characters.
I've tried this:
for %i in (*.txt) do (set fName=%i)
ren %fName% %fName:~0,-11%.txt
But this removes only the last 11 characters.
I've tried to modify this code but I can in no way do what I need.
I think it's a very easy thing for someone who is a little more expert than me so I ask you if you can help me.
Thanks in advance.
I insert below the errors that come to me following the corrections:
C:\Users\---\Desktop\Conversione PDFA>for %fname:~0,50% in (*.pdf) do (set fname=%~ni)
graeiojpoghnpiofsdnpibnwapobnslnsdlekpfèwekrgpjbm was unexpected at this time.
C:\Users\---\Desktop\Conversione PDFA>for %fname:~0,50% in (*.pdf) do (set fname=%~ni)
graeiojpoghnpiofsdnpibnwapobnslnsdlekpfèwekrgpjbm was unexpected at this time.
C:\Users\---\Desktop\Conversione PDFA>for %fname:~0,50% in (*.pdf) do (set fname=%i)
graeiojpoghnpiofsdnpibnwapobnslnsdlekpfèwekrgpjbm was unexpected at this time.
C:\Users\---\Desktop\Conversione PDFA>ren %fName% !fname:~0,50!.pdf
The syntax of the command is incorrect.
C:\Users\---\Desktop\Conversione PDFA>ren %fName% %!fname:~0,50!.pdf
The syntax of the command is incorrect.
for %fname:~0,50% ...: just no.
for %i in (*.pdf) do set fname=%i: yes.
You want to rename several PDF's, so the ren command should be within the loop. That's possible but ugly and error-prone (especially when you are not (yet) firm in cmd syntax) in a single command line, so I wouldn't' suggest it. Your best approach is the use of a batch file. It's much more readable and maintainable.
#echo off
setlocal enabledelayedexpansion
for %%i in (*.pdf) do (
set "fname=%%~ni"
ECHO ren "%%~fi" "!fname:~0,50!%%~xi"
)
See for /? for an explanation of the modifiers %%~ni etc.
See delayed expansion for the usage of !fname! instead of %fname%
NOTE: I "disarmed" the ren command for security reasons by just echoing it. When you have verified, it's exactly what you want, just remove the ECHO
Related
I am trying to write a batch file that will create other, more complex batch files.
This is a portion of my script for right now:
(
echo #echo off
echo for /f "delims=" %%a in (themeset.txt) do set color=%%a&goto setcolor
echo :setcolor
echo color %%color%%
echo pause
) >otherfile.cmd
Theoretically, the output should be a .cmd file with these exact contents:
#echo off
for /f "delims=" %%a in (themeset.txt) do set color=%%a&goto setcolor
:setcolor
color %color%
pause
However, the batch file does not run, and when I attempted to double the %% signs it does not write the entire line correctly.
Any suggestions or solutions would be appreciated.
Max
Magoo's comment beat me to most of the issues.
There is a mostly obscure situation where ECHO text to echo fails, so many people switched to ECHO.text to echo. But somewhere along the way I hit an even more obscure line where that failed, and discovering that semicolon didn't have that problem, I switched to ECHO;text to echo. Which so far, I've not seen any issues.
The FOR /F command has issues, with EOL defaulting to the semicolon being one of them. Some web-page out there made the claim that DELIMS was executed before EOL, so setting EOL to the same as DELIMS would disable it. In my testing it does. But now if we want the whole line, it seems that TOKENS=* disables DELIMS. As far as I know, this is true, but I will admit that I haven't tested that one as much as I would like, so it is probably best to set DELIMS=~, or to similar character that isn't likely to be found in the file.
The % has to be escaped with another percent as in %%, but FOR requires %%, so now you need 4 percents %%%% total.
%%~aa, %%~dd, %%~ff, %%~nn, %%~pp, %%~ss, %%~tt, %%~xx, and %%~zz are all ambiguous. So it probably best to use only capital letters with FOR variables, and probably safest to use only these letters: %%B, %%C, %%E, %%G, %%H, %%I, %%J, %%K, %%L, %%M, %%O, %%Q, %%R, %%U, %%V, %%W, and %%Y See the bottom sections of the help produced by FOR /? for more info on this.
Use the caret to escape special characters. This page, Escape using caret(^), gives some useful info, but its NOT complete. You NEED the caret before the closing parentheses ^), which that page fails to tell you. And to play it safe, I also caret the opening parentheses ^(. But the good thing about that page is that it does points out that when DelayedExpansion is on, you have to double escape the exclamation mark ^^!.
Most of the rest is conventions, I normally capitalize all commands and place a colon in front of all labels, both GOTO :Label and CALL :Label.
The following code:
#ECHO OFF
(
ECHO;#ECHO OFF
ECHO;FOR /F "EOL=~ TOKENS=* DELIMS=~" %%%%L IN ^(themeset.txt^) DO SET Color=%%%%L^&GOTO :SetColor
ECHO;:SetColor
ECHO;Color %%Color%%
ECHO;PAUSE
) >otherfile.cmd
Producted the following file:
#ECHO OFF
FOR /F "EOL=~ TOKENS=* DELIMS=~" %%L IN (themeset.txt) DO SET Color=%%L&GOTO :SetColor
:SetColor
Color %Color%
PAUSE
It is clear from your code that you are not even performing the task in the most efficient manner. The following example will therefore perform the same task, but using another methodology. (i.e. retrieve the first line of the text file content and use it as the color command parameter from another Windows Command Script)
#( Echo #Set /P "colr=" 0^< "themeset.txt"
Echo #Color %%colr%%
Echo #Pause) 1> "otherfile.cmd"
I'm new to Windows cmd and .bat, and to Tesseract. But thanks to this list I've managed a couple of successes.
My first success was this cmd-window line:
tesseract.exe -l eng+lat+ita D:\TIFs\Convivio.tiff D:\TIFs\Convivio
My next success was the .bat file:
:Start
#Echo off
ECHO.
ECHO This is a batch file
ECHO.
PAUSE
BREAK=ON
Set _SourcePath=D:\temp\TIFs\*.tif
Set _OutputPath=D:\temp\TIFs\
Set _Tesseract="D:\temp\Tesseract-OCR\tesseract.exe"
:Convert
For %%A in (%_SourcePath%) Do Echo Converting "%%A"...... &"D:\temp\Tesseract-OCR\tesseract.exe" "%%A" "%_OutputPath%%%~nA"
PAUSE
:End
Set "_SourcePath="
Set "_OutputPath="
Set "_Tesseract="
The problem now is how to include in the .bat file that"-l eng+lat+ita" bit from the cmd-window line.
I got the idea that this is possible from an explanation of the "For" command, which states that "do command" can be followed by "CommandLineOptions" (i.e., "-l eng+lat+ita").
Any help would be much appreciated... 'cause I've been banging my head on this one for hours now...
UPDATE: Found an alternative, but still would like an answer to my question.
I didn't know that "FOR" commands could be run from cmd. So, I pasted the folllowing line in the cmd window:
for %i in (*.tif) do "D:\temp\Tesseract-OCR\tesseract.exe" -l eng+lat+ita "%i" "D:\temp\%~ni"
And, it worked!
As I say, though, how to do this with a .bat file?
#ECHO OFF
SETLOCAL
:Start
#Echo off
ECHO.
ECHO This is a batch file
ECHO.
PAUSE
BREAK=ON
Set "_SourcePath=D:\temp\TIFs\*.tif"
Set "_OutputPath=D:\temp\TIFs"
Set "_Tesseract=D:\temp\Tesseract-OCR\tesseract.exe"
:Convert
For %%A in ("%_SourcePath%") Do Echo Converting "%%A"...... &"%_Tesseract%" -l eng+lat+ita "%%A" "%_OutputPath%\%%~nA"
PAUSE
:End
rem Set "_SourcePath="
rem Set "_OutputPath="
rem Set "_Tesseract="
GOTO :EOF
Since I don't have the tesseract utility, I used another. The above worked for me as I expected with that other utility, so no guarantees with tesseract.
It's normal practice to start a batch with setlocal which makes the clean-up effort unnecessary (hence remmed-out) since an implicit endlocal is executed when the batch terminates, restoring the environment to its initial state.
Assigning values containing quotes is valid but awkward when combining elements. Ditto terminating a value with a backslash. I've converted your code to my preferred syntax. Note that the syntax SET "var=value" (where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned.
Will it work in your situation? Over to you to try.
I've got an issue regarding a text file I'd like to change with a batch file. I was able to trim it to this point.
3539
78060031
523 )
What I need now is to get the numbers in the same line. By the way the text file is not written by my programm. What I need is now to get some backspaces till it looks like this:
353978060031523
I know there is a simple solution, but since I'm very bad in scripting I can't
find it.
Sorry for my bad english and the bad post!
It's the first time I post something here.
Thank you in advance.
This is a duplicated question. But, well, nevermind, I just answer your question.
I don't know what's the purpose of a ")" behind the "523", but since you're just concatenate the string, try out the following script:
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=*" %%a in (hxh-chp.txt) do (
set "concatenate_string=!concatenate_string!%%a"
)
echo !concatenate_string!
pause >nul
The following should do what you expect, that is, concatenate the numerical characters and removing all spaces and the ):
setlocal EnableDelayedExpansion
for /F "usebackq" %%L in ("\path\to\your\text_file.txt") do (
set "CONCAT=!CONCAT!%%L"
)
endlocal & set "CONCAT=%CONCAT%"
echo %CONCAT%
This code makes use of the default behaviour of for /F, where the option tokens=1 and delims is tab and space.
So I was tasked with making a batch file that does a few specific things. I've never worked with batch before, and I'm finding it hard to find tutorials on what exactly I need. (I've done basic tutorials)
I'm trying to get the most currently edited file from a directory. The only thing I've came up with (and I've noticed other people said to do) is a for loop of files in the directory sorted by date and then just get the first file and break the loop.
Some problems:
1) My loop never breaks
2) My ECHO %variable% doesn't work at the end.
#echo off
SET count=0
FOR /f %%i in ('DIR Y:\ /B /O:-D') DO (
IF count==0 (
SET NewestFile=%%i
SET count=1
)
)
#echo on
ECHO %NewestFile%
When I run this, I get:
C:\>testing.bat
C:\>ECHO
ECHO is on.
I am 100% new to Batch. Maybe I'm doing something that this is really picky about? (Other StackOverflow questions have been solved by people just adding aa space or stuff like that)
Your condition is never met because the string count is never equal to the string 0. You need
if !count!==0 (
set NewestFile=%%i
set count=1
)
But then you also need delayed expansion (at the beginning of your batch file):
setlocal enabledelayedexpansion
The problem here is that you need to tell the batch file that there is a variable. Like foo in Perl won't magically resolve to the contents of the $foo variable count in your batch file isn't equivalent to %count% (the variable contents) or !count! (the same, but with delayed expansion).
Delayed expansion is necessary because the whole for loop is parsed at once. And cmd replaces normal (%foo%) variables with their contents during parsing so that during execution only the values remain. So once execution reaches the if there would be the condition 0==0 because that's what count's value was before the loop. Delayed expansion (using the !foo! syntax) expands the variables immediately prior to execution, so this does not happen.
For more help on delayed expansion you can read help set.
Another way would be to just use absence or presence of the count variable:
SET count=
FOR /f %%i in ('DIR Y:\ /B /O:-D') DO (
IF not defined count (
SET NewestFile=%%i
SET count=1
)
)
This works around the problem above because there is no variable to replace during parsing. All we're doing is a run-time check whether the variable count exists.
If you supplied accurate code then you want to get the first line - and this is one way to do that.
#echo off
FOR /f %%i in ('DIR Y:\ /B /O:-D') DO SET "NewestFile=%%i" & goto :done
:done
ECHO %NewestFile%
If you change the dir command to list the files in ascending order instead of descending order, you can use this one-liner which doesn't need any of the common bizarre cmd.exe scripting hacks. It just keeps the last line of output in the NewestFile variable (I guess it might qualify as a cmd.exe scripting hack, but I don't think it qualifies as bizarre):
for /f %%i in ('DIR Y:\ /B /O:D') do set NewestFile=%%i
How would I achieve this:
for i in *.e; do mv $i ${i%-b*.e}.e; done
in a Windows batch file? (It renames files containing "-b" to the part before "-b". Note that this is not necessarily the end of the string! e.g. "file-b-4.e" will become "file.e")
If you really want to do this in batch, this should work
#echo off
setlocal disableDelayedExpansion
for %%F in (*.e) do (
set "var=%%~F"
setlocal enableDelayedExpansion
set "var=!var:-b=.e:!"
for /f "eol=: delims=:" %%A in ("!var!") do (
endlocal
echo ren "%%F" "%%A"
)
)
Edit
The comment by panda-34 alluded to the fact that the original posted code failed if the file name begins with -b. The code above was fixed by incorporating the extension into the replacement string. (thanks panda-34 for alerting me to the problem)
panda-34 also provided an alternate solution that uses command injection with search and replace. The injected command is the REM statement.
The panda-34 solution works as long as the file name does not contain & or ^ characters, but fails if it does.
Below is a modified version of the command injection technique that should work with all valid Windows file names. There are 2 critical mods, 1) make sure the special chars in the file name are always quoted, and 2) do not pass the value as a CALL argument, otherwise ^ will be doubled to ^^.
#echo off
setlocal disableDelayedExpansion
for %%i in (*-b*.e) do (
set old="%%~ni"
call :ren_b
)
exit /b
:ren_b
set v=%old:-b=.e"&rem "%
echo ren "%old:~1,-1%.e" %v%
exit /b
Final Edit (I hope):
As baruch indicates in his comment, the solutions above remove starting with the 1st occurance, whereas the original bash command removes starting with the last occurance.
Below is a version that should be an exact equivalent of the original bash command.
#echo off
setlocal disableDelayedExpansion
set "search=-b"
for %%A in (*%search%*.e) do (
set "old=%%A"
setlocal enableDelayedExpansion
set "new=\_!old:%search%=\_!"
for %%B in ("!new!") do (
endlocal
set "new=%%~pB"
setlocal enableDelayedExpansion
set "new=!new:~2,-1!.e"
echo ren "!old!" "!new:\_=%search%!"
endlocal
)
)
Simple, really
for %%i in (*-b*.e) do call :ren_b %%~ni
goto :eof
:ren_b
set v=%*
set v="%v:-b=.e" ^& rem %
ren "%*.e" %v%
Here's a variant to keep the name till the last -b occurence
setlocal enabledelayedexpansion
for %%i in (*-b*.e) do (
set v=%%~ni
set v=!v:-b=\!
for %%j in ("\!v!") do (
set v=%%~pj
set v=!v:~1,-1!
set v=!v:\=-b!
ren "%%i" "!v!.e"
)
)
It will fail for names containing ! and starting with -b.
P.S, Didn't see, dbenham already provided the equivalent solution, probably with more provisions for terminal cases of file names.
Forget it, some convenient things cannot be done in NT scripting. What you are asking here is not possible to my knowledge. And I've written and maintained complex NT scripts bigger than 50 KiB, using all kinds of tricks. The book "Windows NT Shell Scripting" points out many of these, for the same and more see Rob van der Woude's scripting pages.
I reckon you could do part of this, but certainly not in a one-liner due to how variable expansion works in NT scripting. For example you could extract the part of the string that you expect to be -b and check whether it is -b, then extract the other parts and rename from the original name to the one that is comprised of only the extracted parts.
But you'll likely need ten to fifteen lines to achieve that. In that light, consider using a different scripting language for the purpose. Especially if this is a modern Windows version.
I realize this is not the desired answer (i.e. that this is possible and a sample), but cmd.exe is very limited compared to Bash, albeit by far not as limited as some opponents of traditional batch scripting are pointing out.