I have a batch script located in different folder. ( \test remove\ )
I wish to remove 14 characters from all .csv in another folder ( \test remove\remove from here\ ) the folder it removes the characters from could be anywhere (the sub directory is a example)
little background, the 14 characters is a timestamp (YYYYMMDDHHMMSS), wish to remove the timestamp from .csv files
When I run my script it removes the characters from the folder where the batch script is located.
setlocal EnableDelayedExpansion
set removeFileLocation="C:\...\Desktop\test remove\remove from here\"
for /r %removeFileLocation% %%x in (*.csv) do (
set "oldname=%%~Nx"
set "newname=!oldname:~,-14!"
ren "!oldname!.csv" "!newname!.csv"
)
When running as well I get "The System cannot find the file specified." however it still successfully removes characters from .csv files.
I'd suggest you try
setlocal EnableDelayedExpansion
set "removeFileLocation=C:\...\Desktop\test remove\remove from here"
for /f %%x in (' dir/s/b/a-d "%removeFileLocation%\*.csv" ') do (
set "oldname=%%~Nx"
set "newname=!oldname:~,-14!"
ECHO ren "%%~dpx!oldname!.csv" "!newname!.csv"
)
Notes:
set "removeFileLocation... is changed (1) so that the "rabbit's ears" enclose the ENTIRE assignment, which ensures trailing spaces are NOT included in the value assigned. (2) the trailing \ is removed. (this is a matter of personal choice)
The FOR/F builds a DIR list in memory of the full-filenames only (no headers)
The ren needs to have the filenames's drive and path restored.
The ren is merely ECHOed to ensure that the operation is correct. Remove the ECHO keyword to activate the rename.
What I believe is happening with your original version is that the for/r is re-encountering an already-renamed file OR since you've not assigned a pathname to the file to be renamed, it's finding a .csv in some subdirectory and attempting to rename it in the current directory, but it doesn't exist there or has already been renamed there.
Related
Reviving an old topic once discussed here, as I have a similar problem. The solution proposed in the old thread worked only in half in my case.
I need first to rename various media files (mp4, mp3, wav...) with irregular, sometimes complex names as 1.mp3, 2.mp4, 3.wav, etc. And some time after I need to restore the original filenames. File extensions should remain the same in both cases.
In a more specific case of renaming .raw files Helbreder proposed two .bat scripts. The first .bat changes filenames to 1.raw, 2.raw, 3.raw, etc. and creates corresponding individual .txt files each of which keeps the original filename. The second .bat takes the original filenames from individual .txt files and renames 1.raw, 2.raw, 3.raw, etc., back to the original.
For my purpose I slightly modified the first .bat proposed, and this works perfectly well:
#echo OFF
#setlocal ENABLEDELAYEDEXPANSION
set I=1
for %%G in (*.mp3 or *.3gp or *.wav or .mp4) do (
set ORIGINAL_NAME=%%~nG
set ORIGINAL_EXTENSION=%%~xG
(
REM Try to rename file
ren "%%G" "!I!"!ORIGINAL_EXTENSION!
) && (
REM Renaming was successful
> "!I!.txt" echo !ORIGINAL_NAME!!ORIGINAL_EXTENSION!
set /A I+=1
) || (
REM Renaming was a failure
echo Cannot rename [!ORIGINAL_NAME!] file.
)
)
#endlocal
Put in a destination directory, this .bat renames all media files, keeping the correct extensions, and generates a set of .txt files each of which contains the original filename with extension.
For instance, 1.txt contains a string "Play 2019-03-06 in C.mp3" which was the original filename.
Then I need to reverse the original filenames and I run the second unmodified Helbreder's .bat. For commodity purpose I paste it here:
#echo OFF
#setlocal ENABLEDELAYEDEXPANSION
for %%F in (*.txt) do (
set BASENAME=%%~nF
REM Read original name from txt file
for /F %%G in (%%F) do (
REM iterate over all corresponding files
for %%H in (!BASENAME!.*) do (
set EXTENSION=%%~xH
REM Remove dot from extension string
set EXTENSION=!EXTENSION:~1!
if not "!EXTENSION!" == "txt" (
REM Process files
(
REM try to rename corresponding file to old name
ren "!BASENAME!.!EXTENSION!" "%%G.!EXTENSION!"
) && (
REM Operation was successful - remove TXT file
del /F /Q "%%F"
) || (
REM Something went wrong
echo Cannot restore old name for file [!BASENAME!.!EXTENSION!].
)
)
)
)
)
#endlocal
As my filenames may be complex and often include blank spaces, this second .bat works in a half-successful way.
It reverted the first original filename "Play 2019-03-06 in C.mp3" written to a 1.txt with extension, as simply "Play.mp3". It also ignored a part of the second complex filename which followed blank space, keeping only "2007-03-06.mp3" instead of "2007-03-06 output.mp3". And it successfully reverted only those filenames which were composed of numbers and underscores, without blank spaces.
As far as I understand, the issue consists in the way the second .bat retrieves the filename from the text string kept in .txt file. The first blank space occurring in the text line is considered as the end of a filename.
Could you kindly suggest a solution for reverse renaming of any files from the correspondent .txt record, which may contain letters, numbers and blank spaces (and maybe special characters, like "&" and some others).
Following Compo's advise I tried another code from the old post, this time proposed by Jeb.
After a slight modification to make it match to different file types and - important! - to keep their original extensions, the code seems to work, but with issues.
When there is more than one dot in the filename the name revert code does not restore it completely, even though it is correctly saved in the .txt file by the rename batch. For example the second batch truncates "Play 2020.10.12.mp4" to "Play 2020" and does not wish to restore the extension.
Placed in directories with many files the rename batch sometimes does not rename a part of the list, sometimes does not do the job at all and sometimes renames all files flawlessly. I first thought the partial script dysfunction might be related to the presence of special signs in the filenames, like commas or parenthesis. But no, when I delete special signs, this changes nothing. Just puzzled.
So, the new version of code is only partially solving the problem. Is there something to correct in the code, to make it more universally working? Which solution could be applied in these two cases?
I divided the code into two separate .bat files to rename and to revert original filenames.
The both follow.
Rename:
#echo off
set cnt=0
del Names.txt > nul 2>&1
echo Running Batch Rename
for %%f in (*.mp3 or *.mp4 or *.3gp or *.wav) do (
set "file=%%f"
set "EXTENSION=%%~xf"
CALL :renameToNumber
)
:renameToNumber
set /A cnt+=1
set "number=00000%cnt%"
set "number=%number:~-4%"
(echo %number% %file%) >> Names.txt
ren "%file%" %number%"%EXTENSION%"
exit /b
Revert the original names:
for /F "tokens=1,*" %%A in (names.txt) DO (
set "number=%%A"
set "filename=%%~nB"
call ren %%number%%.* "%%filename%%.*"
call echo ren %%number%%.* "%%filename%%.*"
)
exit /b
I have a number of excel files nested in separate folders in a directory. Each of these folders also has any number of other files, but I am only interested in the excel files. I am trying to copy all the excel files into a new folder.
What I have been able to create is this.
for /r "C:\Folder One\Folder Two" %%f in (*.xls, *.xlsm) do #copy "%%f" "C:\Users\ME\Desktop\New Excel Folder"
The problem is, each of the subdirectories may have another one or two folders which may or may not have an errant excel file that I am not interested in. My solution grabs every single excel file in the entire directory structure.
I am looking for a way to only get the excel files from all of the the third level down folders, so everything in c:\Folder One\Folder Two\THESE FOLDERS AT THIS LEVEL, but no deeper. Hopefully that makes sense.
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include 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\t w o"
SET "destdir=u:\your results"
for /r "%sourcedir%" %%f in (*.xls, *.xlsm) do FOR /F "tokens=4,5delims=\" %%q IN ("%%~dpf") DO IF "%%r"=="" FOR %%e IN (.xls .xlsm) DO IF /i "%%e"=="%%~xf" ECHO #copy "%%f" "%destdir%"
GOTO :EOF
I've changed directorynames to suit my test setup.
The #copy command is echoed for verification. Remove the ECHO to actually execute the copy.
Two stages in the filtering. First, check the number of \ characters in the filepath - %%r will be non-empty when the required directory-level is exceeded. The filename is then checked explicitly for the required extensions because filename.xlsx will have an automatically-by-default short filename generated which will match .xls.
Tokens:
delims=\xyz" defines a delimiter character-set of ["\","x","y","z"]. I always place the delims= option last so that any characters appearing between delims= and " are included in the delimiter character-set.
The string under examination is viewed as
[[delimiter-sequence]][token1][delimiter-sequence][token2][delimiter-sequence][token3][delimiter-sequence][token4][delimiter-sequence][token5]...
where a delimiter-sequence is a sequence of any of the delimiters. The initial delimiter-sequence is optional.
So, with delimiters set to \ alone, a sample string, c:\Folder One\Folder Two\THESE FOLDERS AT THIS LEVEL\but no .deeper
will be parsed as
Token 1 c:
Token 2 Folder One
Token 3 Folder Two
Token 4 THESE FOLDERS AT THIS LEVEL
Token 5 but no .deeper
Token 6 empty
However, the code I posted applied the for ...%%q to %%~dpf, not %%f nor %%~dpnxf nor %%~ff so the string to be parsed was c:\Folder One\Folder Two\THESE FOLDERS AT THIS LEVEL\ where Token 5 would be empty. Had there been an extra directory-level, then Token 5 would not be empty.
I'd suggest that either a stray delimiter has been introduced, or some string other than %%~dpf is being parsed.
I never use %%f for filename, regardless of its original attractiveness, as f is a metavariable-modifier and subject to typos.
I have a task to rename a file and place another file with same name in the same folder
Like for e.g. a folder C:/test I have multiple files .txt (suppose test.txt is the one needed rename and replace)
I want to rename test.txt to test_bkp%date% and place new file there.
Need help to start the logic.
#ECHO OFF
SET "sourcedir=C:\Users\test\new"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%C:\Users\Test\new\%filenames%.txt" '
) DO (
SET "filename=%%a"
ECHO REN "%C:\Users\Test\new\%%a C:\Users\Test\new\%%a_bk_date.*%"
)
GOTO :EOF
Let me explain what I am trying to achieve. I get file with updated data often. I cannot just go ahead and replace the old file with new. I have to take a backup and place the new file in the folder.
This is my first try using batch scripting
As soon as you write a new version of a file into the same folder than the original (with the same name), it's already too late to rename the original - it doesn't exist anymore. You need two folders: one that receives new versions (new) and one where you keep your renamed files plus the new ones (old)
#ECHO OFF
setlocal
set "source=C:\Users\test\new"
set "destin=C:\Users\test\old"
set "files=*.txt"
REM for every matching file in the source folder:
for %%A in ("%source%\%files%") do (
REM if there is such a file in the destination folder, rename it:
if exist "%destin%\%%~nxA" ren "%destin%\%%~nxA" "%%~nA-%date%%%~xA"
REM only then copy the file:
copy "%%~fA" "%destin%\"
)
This will fail if you run it more than once per day. (More code needed to handle that; for example, adding time too)
It will also fail if your %date% contains characters that are not allowed in file names (my %date% looks like 29.01.2019). (More code needed to handle that; for example %date:/=-%)
I want to create a script which should copy files from one folder to another.
Since a file can be of a large size, of up to 1000 MB, it may take few seconds
or a minute to completely copy it. While this is being happened, I want the filename in a destination folder to be prefixed with an underscore(_).
Once the file is completely copied over to a destination folder, then the _ should be removed from the filename. The purpose of doing this is to make sure that another process should not pick up the incomplete file from the destination folder.
How can we do this using a batch script? Currently my batch file is copying and moving the file to another folder but I don't know how can i prefix underscore and then remove again from the filename after the file is completely moved.
Here is my 2 line code which is copying and moving the file.
copy %1\Customer_*.xml C:\Users\ard\Documents\Folder1
move %1\Customer_*.xml %1\Archive
If this can't be done using batch script, then VB script should also work
What you want, in words:
For each affected file in C:\source:
Copy file x to C:\destination\_x
Rename file C:\destination\_x to C:\destination\x
and in Windows batch code, with a few extras:
#echo off
setlocal
set "SOURCE=%1"
set "DESTINATION=C:\Users\ard\Documents\Folder1"
for /f "usebackq delims=" %%x in (`dir /b "%SOURCE%\Customer_*.xml"`) do (
if exist "%DESTINATION%\%%x" (
echo %%x - already exists at destination
) else (
echo %%x
copy "%SOURCE%\%%x" "%DESTINATION%\_%%x" > NUL && rename "%DESTINATION%\_%%x" "%%x"
)
)
Notes:
the for loop can iterate a command's output line-wise
in our case, that command is dir /b "%SOURCE%\*.xml", i.e. the "bare" list of matching files in the source folder
usebackq means the command is delimited by backticks, which allows using double quotes inside the command itself
delims= sets the field delimiters to "none", otherwise for would split each filename into tokens if it contained spaces
> NUL suppresses the "1 file(s) copied." success messages from copy
&& means that rename is only executed if copy was successful
Removing a prefix is not trivial, but removing a suffix (new extension) is simple. So I would append a new extension like .inProgress. You can then COPY and RENAME a collection of files with two simple commands using wildcards.
But the MOVE command does not allow renaming multiple files, so a FOR loop would be required. I'll show the code, but I don't think it is really necessary in the OP's scenario. It looks to me like the source and destination folders are on the same drive, so the move should be virtually instantaneous, and there should be no need to use a temporary intermediate name.
copy "%1\Customer_*.xml" "C:\Users\ard\Documents\Folder1\*.*.inProgress"
ren "C:\Users\ard\Documents\Folder1\*.inProgress" *.
for %%F in ("%1\Customer_*.xml") do (
move "%%F" "%1\Archive\%%~nxF.inProgress"
ren "%1\Archive\%%~nxF.inProgress" *.
)
See How does the Windows RENAME command interpret wildcards? for information on why the rename works.
Note that all the copied files will show up as ".inProgress" until the entire COPY operation has completed. If you want each file to be available as soon as possible, then a FOR loop is needed for the COPY as well:
for %%F in ("%1\Customer_*.xml") do (
copy "%%F" "C:\Users\ard\Documents\Folder1\%%~nxF.inProgress"
ren "C:\Users\ard\Documents\Folder1\%%~nxF.inProgress" *.
)
My example copies from src to dest with a new name, then restores back the old name:
bn is the basename of the source file.
for %%a in (src\*.xml) do (
set bn=%%~nxa
copy %%a dest\!bn!_
rename dest\!bn!_ !bn!
)
I want to replace the content paths defined into the file i.e logging.properties to the desired location path of the jboss7 location .
Basically i'm using installer where i have to browse my jboss7 folder and locate it to any desired location of the user . But in few files of jboss7 there are some hardcoded path defined like in given logging.properties file.
I need to change that hard coded path to the desired location path.
As of now i'm having repl.bat and file test.bat files in the same folder.
repl.bat helper file could be find in following link:-
http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
I just copied the code and created repl.bat file.
test.bat file :-
#ECHO OFF
SETLOCAL
SET "folder="
FOR /r "C:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
FOR /r "D:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
:got1
echo "%folder%"
PAUSE
set "newpath=%folder%"
set "newpath=%newpath:\=\\%"
echo "%newpath%"
PAUSE
type "logging.properties" | repl "(Directory=).*(\\\\standalone\\\\)" "$1%newpath%$2">"logging.properties.tmp"
PAUSE
move "logging.properties.tmp" "logging.properties"
PAUSE
GOTO :EOF
PAUSE
Here in this test.bat file , i'm searching a file tintin.txt file and setting the path into a variable name as 'folder'. tintin.txt file is just inside the folder of jboss7.This is because of the possibilities of more than one jboss7 application server folder into the system.
Till now i have got the path i.e "C:\Users\Anuj\Desktop\jboss7\" and set into the variable 'folder'.
Now there is file named logging.properties into the folder location
C:\Users\Anuj\Desktop\jboss7\standalone\configuration
logging.properties :-
com.latilla.import.uploadDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\ standalone\\uploads
com.latilla.import.maxFilesUploadNumber=10
com.latilla.export.templateFile=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\templates\\GDV_HDI_Format.xls
com.latilla.etl.pluginsRootDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\cloverETL\\plugins
com.latilla.etl.templatesDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\etl
com.latilla.db.user=postgres
com.latilla.db.pass=password
repl.bat helper file helps to replace the url path with the desired path i.e path set to variable name 'folder'.
I want to replace the C:\progra~2\Latilla\C4i\jboss7\ with the path set to variable name 'folder'.
Note :-
here in logging.properties file path contents is having different format of path i.e C:\
means double slash. \
Might be the script that i have tried test.bat is incorrect.
When i double click the test.bat file i got error.
Although I can't help you with fixing the issue you are getting while using the repl.bat file, I can suggest a different way of solving the initial problem of path replacement.
If the jboss7 string is guaranteed to be present in all the original paths in your configuration file(s), you could try the following approach:
#ECHO OFF
SETLOCAL DisableDelayedExpansion
FOR /F "delims=" %%A IN ('DIR /B /S C:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
FOR /F "delims=" %%A IN ('DIR /B /S D:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
GOTO :EOF
:got1
SET "propfile=%CD%\standalone\configuration\logging.properties"
IF NOT EXIST "%propfile%" GOTO :EOF
SET "tempfile=%TEMP%\logging.properties.tmp"
FIND /I /V "jboss7\\" >"%tempfile%"
>>"%tempfile%" (
FOR /F "tokens=1,* delims=" %%I IN ('FIND /I "jboss7\\"') DO (
SET "pathname=%%J"
SETLOCAL EnableDelayedExpansion
IF NOT "!pathname!" == "!pathname:*jboss7\\=!" (
SET "pathname=%__CD__:\=\\%!pathname:*jboss7\\=!"
)
ECHO %%I=!pathname!
ENDLOCAL
)
)
ECHO Old file "%propfile%":
TYPE "%propfile%"
ECHO =======================================
ECHO New file:
TYPE "%tempfile%"
PAUSE
:: uncomment the next line once you have verified the replacement works correctly
::MOVE "%tempfile%" "%propfile%"
Searching for the tintin.txt file has been changed slightly so as to possibly make the process faster. Instead of iterating over every directory and checking if it contains the file, the loops now read the output of DIR, which returns only actually existing entries.
Note that you could also use a FOR /R loop, as in your present code, with the same effect i.e. returning only existing paths, but the IN clause would need to contain a mask rather than a normal name, but that would have to be a mask that couldn't match anything else in your system than just tintin.txt. For instance, if you knew for certain that there could be no file called tintin.txt1 or tintin.txtx or anything else where tintin.txt is followed by exactly one character, you could use the following template instead:
FOR /R "C:\" %%A IN (tintin.txt?) DO (CD /D "%%~dpA" & CALL :got1)
and same for D:\. That would return only references to files actually existing and matching the mask.
Also, you can see that the loops do not jump (GOTO) to the got1 label but instead call the got1 subroutine. With that change, it is possible to process many application instances in one go. I don't know yours can be installed multiple times. If not, you'll probably want to change it back to GOTO.
The subroutine in my script is referencing the config file using its full path as specified in your description (...\standalone\configuration\logging.properties). For some reason, in your script the file is referenced simply by its name, even though there's no preceding CD or PUSHD command changing the current directory to the location of the file. I assumed you were trying to simplify your script and omitted that bit, whether intentionally or not. Otherwise I may have missed something in your explanation and/or script.
After verifying that the config file exists at the expected location, the replacement itself is done in this way:
All the non-path config lines are written to a temporary file with one go.
Every config line containing a path is processed in this way:
if it does not contain the jboss7\\ string, it is omitted;
otherwise the part of the path up to and including jboss7\\ is removed;
the current directory is inserted before the remaining part (after every \ is replaced with \\);
the new value is put back into the config line;
the update line is added to the same temporary file.
The old version is of the configuration file replaced with the new one.
Obviously, the script may change the order of lines in the processed file, but it is assumed that that doesn't matter.