As can be seen in the image I have folders with "." in them I would like to replace these with a "_" using CMD is there a method to do this.
cmd.exe shell scripting is the worst approach for anything more than #echo off :-)
But ok.
You can use the enhanced shell command set to replace characters in a variable:
set DUH=FBB
echo %DUH:B=O% -> FOO
So, for your problem, you need to read all folders and get them in a variable, so you can replace .=_ and then rename.
First batch: rena.cmd iterates over your folders
#echo off
for /D %%i in ( *.* ) do call rena2.cmd %%i
Second batch: rena2.cmd handles the rename
#echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set TONAME=%~1
move %1 "%TONAME:.=_%"
exit /B
This can be done in one script, feel free to fiddle it together, I won't :-)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir\t w o"
FOR /f "delims=" %%a IN (
'dir /b /ad "%sourcedir%\*.*" '
) DO (
SET "dirname=%%a"
SET "dirname=!dirname:.=_!"
IF "!dirname!" neq "%%a" ECHO(REN "%sourcedir%\%%a" "!dirname!"
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
Dimply perform a directory-list, change the . to _ and if a change was made, perform the rename.
Related
The batch file below intends to find all files that don't match the set pattern and delete them. However, it won't execute at all. Looks like there is syntax issue in the IF statement that I couldn't find.
SETLOCAL ENABLEDELAYEDEXPANSION
SET SHARE_FOLDER=\\blyfs01\teams$\Hadoop\Workday\
SET WKDAY_FNAME=WKDY_HADOOP_PTODATA
FOR %%F in ("%SHARE_FOLDER%*.*") DO ( SET FNAME=%%~nxF & IF !FNAME:~0,28!==!WKDAY_FNAME!_%date:~-4%%date:~4,2%%date:~7,2% ( #ECHO DO #DEL %%F) )
elzooilogico got it right. It literally is the quote that made it work!
FOR %%F in ("%SHARE_FOLDER%*.*") DO ( SET FNAME=%%~nxF & IF "!FNAME:~0,28!" NEQ "!WKDAY_FNAME!_%date:~-4%%date:~4,2%%date:~7,2%" (#ECHO #DEL %%F) )
OK, I apologize ahead of time for a) using an old, crappy technology (BAT files) and b) asking what seems to be a redundant question. I'm limited in the technology I'm allowed to use in this particular case and after looking at dozens of posts on the subject I can't find anything I can adapt to what I need.
I have a directory structure that looks like this:
A
B
C
D
etc...
XYZ
more folders
My BAT file is located outside this files system. I need to inspect it starting at level "C" and need to find the "XYZ" directory. The folders between C and XYZ can have variable names depending on the environment in which the files were created. I need to end up with a string that consists of the directory names from C through XYZ (i.e. "C\D\E\F....\XYZ") that I can put into a variable so when my BAT file is completed I can reference the variable and run another command.
I've looked at posts using FIND and FOR but I can't seem to figure out how to a) limit the string to the starting directory (for example when I combine FOR with DIR I get "A\B\C...") and how to stop when I get to "XYZ"...
Any help is greatly appreciated.
This should work in most situations:
#echo off
setlocal enableDelayedExpansion
set "root=c:\a\b\c"
set "target=xyz"
for %%R in ("%root%") do for /f "delims=" %%F in (
'dir /b /s /ad "%root%\%target%"'
) do (
set "fullPath=%%F"
set "relpath=!fullPath:%%~dpR=!"
)
echo !relpath!
It can fail if any of your paths contain ! or =. There are solutions for this, but the code is significantly more complicated.
EDIT
Actually, there is a relatively simple solution using FORFILES that should work in all situations. (Assuming your version of Windows has FORFILES)
#echo off
setlocal disableDelayedExpansion
set "root=c:\a\b\c"
set "target=xyz"
for /f "delims=" %%F in (
'forfiles /p "%root%" /m "%target%" /s /c "cmd /c if #isdir==TRUE echo #relpath"'
) do set "relpath=%%~F"
for %%R in ("%root%") do set "relpath=%%~nxR%relpath:~1%"
echo %relpath%
The only restriction is the code has to change slightly if your result contains poison characters like &. In that case you need to add quotes to the final ECHO statement, or else enable delayed expansion at the end and use echo !relpath!
For a) question:
FOR /F "TOKENS=*" %%d IN ('DIR A\B\C\XYZ /S /AD /B') DO SET variable=%%d
For a) and b) question:
FOR /D /R "A\B\C" %%d IN (*.*) DO IF /I "%%~nxd"=="XYZ" (SET variable=%%d& GOTO :EOF)
but this will exit batch script, so you need:
... your batch code
CALL :GET_XYZ
... your batch code
GOTO :EOF
:GET_XYZ
FOR /D /R "A\B\C" %%d IN (*.*) DO IF /I "%%~nxd"=="XYZ" (SET variable=%%d& GOTO :EOF)
ECHO XYZ not found!
GOTO :EOF
I have and will have files which are named "x_1.txt x_2.txt x_3.txt, ..." my other program where I input these files cannot recognize the order so it sorts like this "x_1.txt , x_101.txt , x_2.txt"). a solution is to rename the files to x00001.txt , x00002.txt , ....
I have so far wrote the .bat file below, but two problems I have which , I'd be very glad if you help me solve them :
1- how can I remove the 'number'.txt from string x_'number'.txt
2- (solved) how can I use the variable of this string to rename the file name ( the rename part of this file is not working!)
cls
setlocal enabledelayedexpansion
set /A count=100000
for %%f in (*.txt) do (
set /a count+=1
set str=!count:~1!
echo !str!
echo %%f
set filename=%%f
set filename=!filename:~0,5! /Comment: here I want to just keep the x_ part which I don't know how"
echo !filename!
set str3=!filname!!str!
echo !str3!
/// ren %%f !str3!.txt /Comment: Here I cannot use the variable str3,
call:renamer %%f !str3!
)
:renamer
ren %1 %2.txt
Thanks in advance
If the following conditions are true:
You want to rename all of your .txt files in the current folder
All of the .txt files have exactly one _ in the name, immediately before the number
None of your file names contain !
Then the following will work
#echo off
setlocal enableDelayedExpansion
for %%F in (*.txt) do for /f "tokens=1,2 delims=_." %%A in ("%%F") do (
set num=0000%%B
ren "%%F" "%%A!num:~-5!.txt"
)
But to eliminate the conditions requires much more complicated code.
Here is one robust solution that should properly rename all files that meet the template.
It allows for multiple _ in the name.
It only renames files with a name that ends with _NNN.txt where NNN is a number
It properly handles ! in the file name.
Note that it will not properly handle numbers that exceeds 99999. It is simple to expand the degree of 0 padding.
#echo off
setlocal disableDelayedExpansion
pushd .
subst #: .
#:
for /f "eol=: delims=" %%F in ('dir /b /a-d *.txt^|findstr /er "_[0-9]*.txt"') do (
set "name=%%~nF"
setlocal enableDelayedExpansion
for /f "eol=: delims=" %%A in ("!name:_=\x!") do (
endlocal
set "file=%%F"
set "name=%%~pA"
set "num=%%~nA"
setlocal enableDelayedExpansion
set "num=0000!num:~1!"
set "name=!name:~1,-1!"
ren "!file!" "!name:\x=_!!num:~-5!.txt"
endlocal
)
)
popd
subst /d #:
i need to copy test.swf to all subfolders of c:/test folder's that doesn't contain "git" word
just tried something like that but not worked
#setlocal enableextensions enabledelayedexpansion
#echo off
for /r %%a in (.) do
(
if not x%a:git=%==x%a% do
(
#copy "C:\test.swf" %a > nul
)
)
endlocal
There is certainly nothing wrong with using vbscript :-) (see OP's answer)
But I thought I would point out where your batch code went wrong.
The left paren must go on the same line as the IF or DO, and there must be a preceding space.
DO is not used with IF
You also need the FOR /D option to go along with /R. Without it you will get files instead of directories.
Your . will include the parent directory. You want * instead to get just the children.
I'm not sure about your requirement, but I assume a path like C:\test\_git_\test should get the file because the folder name does not contain "git" (though the parent does). Your code would look for git anywhere in the path.
All FOR variables must be referenced with double percents as in %%a when in a batch file. You were not consistent.
You cannot perform search and replace on a FOR variable, only on environment variables.
Additional points for improvement, though not errors:
It is extremely rare that enableExtensions is needed. It is enabled by default.
Better to put #echo off at the top then prefix each command with #.
You enabled delayed expansion, but did not use it. Although a correct solution using your algorithm would require it.
Here is the correct code for your algorithm. (actually none of the code solutions below have been tested, but I think I got them correct)
#echo off
setlocal enableDelayedExpansion
for /d /r "c:\test" %%F in (*) do (
set "name=%%~nxF"
if "!name:git=!" neq "!name!" copy "c:\test.swf" "%%F" >nul
)
The above usually works. But it fails if a folder name contain ! because delayed expansion would corrupt the expansion of %%F. The solution is to toggle delayed expansion on and off within the loop.
#echo off
setlocal disableDelayedExpansion
for /d /r "c:\test" %%F in (*) do (
set "name=%%~nxF"
setlocal enableDelayedExpansion
if "!name:git=!" neq "!name!" (
endlocal
copy "c:\test.swf" "%%F" >nul
) else endlocal
)
But there is a much simpler method. You can pipe the results of DIR to FINDSTR with a regex that will filter out folders with "git" in the name. Then use FOR /F to process the results.Edit - I simplified the regex.
#echo off
for /f "delims=" %%F in (
'dir /ad /s /b "c:\test\*" ^| findstr /virc:"git[^\\]*$"'
) do copy "c:\test.swf" "%%F"
The entire process can be done on one line from the command line
for /f "delims=" %F in ('dir /ad /s /b "c:\test\*" ^| findstr /virc:"git[^\\]*$"') do #copy "c:\test.swf" "%F"
just did it by vbscript
Const SourceDir = "C:\source"
Const TargetDir = "C:\target\"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(TargetDir)
Set colSubfolders = objFolder.Subfolders
Set dosyalarklasor = objFSO.GetFolder(SourceDir)
Set dosyalar = dosyalarklasor.Files
For Each objSubfolder in colSubfolders
if not instr(objSubfolder.Name,".git") > 0 then
For Each dosya in dosyalar
objFSO.CopyFile dosya, TargetDir & objSubfolder.Name & "\"
Next
end if
Next
I have a windows boot pen that runs a batch file when it starts up, all it needs to do is copy a large list of files specified in a text file from the machine to the boot pen.
I made a test run on my PC before making the boot pen and thought this should work
#echo off
set DRIVE=c
for /F "tokens=*" %%a in (e:\test\files.txt) do call :amendDirectoryAndCopy %%a
pause
:amendDirectoryAndCopy
set DEST=%~1
set DEST=%DEST:~1%
echo set DEST=%DRIVE%%DEST%
echo xcopy %~1 %DEST%
all it should do is for each file, remove the first character of the string, add "c" to the beginning which gives the destination directory, then perform an xcopy. I find the output confusing as "#echo set "DEST=%DRIVE%%DEST%" outputs what I would expect, the correct directory on C: such as
c:\test\folder\file.txt
but the xcopy outputs
xcopy e:\test\folder\file.txt :\test\folder\file.txt
the drive letter is missing on the destination.
I believe SetLocal EnableDelayedExpansion is needed along with its counterpart ! replacement of % in variable expansion to get your code to work.
I am away from my Windows machine right now, so I cannot test the syntax, but off the top of my head, something like this should work:
SetLocal EnableDelayedExpansion
#echo off
set drive=c
set ready_to_move=0
set file_list=e:\test\files.txt
if "!ready_to_move!" == "1" (
set echo=
) else (
set echo=echo
)
for /F "eol=; tokens=1 delims=" %%f in ('type "!file_list!"') do (
set source=%%~f
for /f "tokens=* delims= " %%s in ("!source!") do set source=%%s
set destination=!drive!!source:~1!
!echo! xcopy "!source!" "!destination!"
)
Does this work for you?