I'm a newbie at this but have spent the afternoon searching your forums. While there are several posts about the ren command i can't seem to get mine to work?!
I would like to change:
A22-7000
A22-7001
A22-7003
to:
A24-7000
A24-7001
A22-7003
I opened the cmd window in the folder location and tried various forms of the following:
ren *A22 *A24
I know this should be easy but it's been driving me insane! Also, if anyone has a link to good tutorials where I can learn this sort of this that would be great!
Thanks!
you got the concept of wildcards wrong.
*A22 means "anything that ends with A22"
* means "any count of characters"
? means "one character"
What you want is probably:
ren A22* A24*
A22* means "anything that starts with A22 followed by any number of chars"
first you should certain you want change folder or file name when you use just ren that rename all find with your wild card !
see my example
if you have A22-7000 file and folder when you ren A22* A24* you change all folder and file if you want change
just folder
random.bat
dir /A:D /b | findstr.exe /n /R "a*" > s:\sites\file-count.txt
FOR /F "tokens=1-10 delims=:" %%A IN ('type "s:\sites\file-count.txt"') do set NUMBER-OF-FILES=%%A
FOR /L %%A IN (1,1,%number-of-files%) DO CALL rename.bat %%A
rename.bat
:rename
FOR /F "tokens=1-10 delims=:" %%A IN ('type "s:\sites\file-count.txt" ^|
findstr "%1:"') do ren %%B a24-%RANDOM%
just file :
random.bat
dir /A:-D /b | findstr.exe /n /R "a*" > s:\sites\file-count.txt
FOR /F "tokens=1-10 delims=:" %%A IN ('type "s:\sites\file-count.txt"') do set NUMBER-OF-FILES=%%A
FOR /L %%A IN (1,1,%number-of-files%) DO CALL rename.bat %%A
rename.bat:
FOR /F "tokens=1-10 delims=:" %%A IN ('type "s:\sites\file-count.txt" ^|
findstr "%1:"') do ren %%B a24-%RANDOM%
also you can do this with powershell script like
just for folder
gci -Directory -Filter A22* | foreach { Rename-Item $_.Name -NewName A24* }
just for file
gci -file -Filter A22* | foreach { Rename-Item $_.Name -NewName A24* }
Related
ECHO ===FILES TO TRANSFER===
FOR /f "usebackq tokens=*" %%G IN (`DIR /B /S "%~dp0Files"`) DO #ECHO %%G
The output is the full path of the file/dir but I want to make it simpler by removing %~dp0's path from the output
This is the methodology I'd suggest you incorporate, which protects filenames which may include ! characters and limits the output to files, as per your stated requirement:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /F Delims^=^ EOL^= %%G In ('Dir /B/S/A-D "%~dp0Files" 2^>NUL')Do (
Set "_=%%G" & SetLocal EnableDelayedExpansion
Echo(!_:*%~dp0Files=.! & EndLocal)
Pause
If you'd prefer not to have a relative path type output then change !_:*%~dp0Files=.! to !_:*%~dp0Files\=!
Alternatively, you could grab the relative paths using the slower, forfiles.exe utility:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE Echo #RelPath"
If you prefer it without doublequotes then this modification should do that:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE For %%G In (#RelPath)Do Echo %%~G"
And if you wanted it without the leading .\ then perhaps:
%__AppDir__%forfiles.exe /P "%~dp0Files" /S /C "%__AppDir__%cmd.exe /D/Q/C If #IsDir==FALSE For /F 0x22Tokens=1*Delims=\0x22 %%G In (#RelPath)Do Echo %%H"
You could also do this by leveraging powershell.exe:
%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoProfile Get-ChildItem -Path "%~dp0Files" -File -Force -Name -Recurse
which could possibly be done, (not recommended), in as short a line as:
powershell -NoP ls "%~dp0Files" -File -Fo -Na -Rec
just remove %~dp0 from each entry (Note: that doesn't work with %%G metavariables, you have to use a "normal" environment variable):
#echo off
setlocal enabledelayedexpansion
ECHO ===FILES TO TRANSFER===
FOR /f "usebackq tokens=*" %%G IN (`DIR /B /S "%~dp0"`) DO (
set "file=%%G"
echo !file:%~dp0=!
)
To retrieve the relative path to a given root without string manipulation, you could use the xcopy command with its /L option, which lists relative paths to files it would copy without /L:
pushd "%~dp0" && (
for /F "delims= eol=|" %%G in ('xcopy /L /S /Y /I "Files" "%TEMP%" ^| find "\"') do (
echo(%%G
)
popd
)
pushd and popd are used to change into and return from the root directory, respectively.
The find command is used to suppress xcopy's summary line # File(s).
I want to get the latest 5 files in a directory.
This gave me the latest file:
FOR /F "delims=|" %%I IN ('DIR "*.yaml" /B /O:D') DO SET NewestFile=%%I
Any help is greatly appreciated
The following example is intended to perform the task as laid out in your question and as implied by my advisory comment:
#Echo Off
SetLocal DisableDelayedExpansion
For /F "Delims==" %%A In ('"Set Newest[ 2>NUL"')Do Set "%%A="
For /F "Tokens=1* Delims=:" %%A In (
'"Dir /B/A:-D/O:-D/T:W "*.yaml" 2>NUL|FindStr /LINE ".yaml""'
)Do If %%A LEq 5 (Set "Newest[%%A]=%%B")Else GoTo :Next
:Next
Set Newest[ 2>NUL&&Pause
I have used the most recently written in the above example and the last line was included just to show you any variables set within the For loop.
Here is another way to get the five (5) newest files according to "last write time." Be sure to change the -Path directory to yours.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "delims=" %%f IN ('powershell -NoLogo -NoProfile -Command ^
"Get-ChildItem -Path "C:\src\t" -Filter '*.yaml' |" ^
"Sort-Object -Property LastWriteTime -Descending |" ^
"Select-Object -First 5 |" ^
"ForEach-Object { $_.FullName }"') DO (
SET "NEWFILE=%%~f"
ECHO Do something with "!NEWFILE!"
)
I have a snippet of code this site helped me with and I would like to alter to behave in a different way if possible?
Running the file on a local PC directly will scan the user profile folders, omits system profiles (to avoid unnecessary scanning) and deletes 2 specified folders from every users app data local folder.
What I need to do now is run it across the network where I have a list of hostnames and do it that way. The below is working running directly on the PC.
For /F "Skip=1 Delims=" %%A In (
'"WMIc Path Win32_UserProfile Where (Special!='True') Get LocalPath"'
) Do For /F "Delims= " %%B In ("%%A") Do (
For %%I In (Folder1 Folder_2) Do (If Exist "%%B\AppData\Local\%%I\" (
RMDIR "%%B\AppData\Local\%%I" /S /Q >nul 2>&1)
)
)
I would like to change it to something like
for /f "usebackq tokens=*" %%A in ("%~dp0hostnames.txt") do (
For /F "Skip=1 Delims=" %%A In (
'"WMIc Path Win32_UserProfile Where (Special!='True') Get LocalPath"'
) Do For /F "Delims= " %%B In ("%%A") Do (
For %%I In (Folder1 Folder_2) Do (If Exist "\\%%B\C$\AppData\Local\%%I\" (
RMDIR "\\%%B\C$\AppData\Local\%%I" /S /Q >nul 2>&1)
)
)
I have had a go but it's getting beyond my limited knowledge, I think I need delayedexpansion and also move on the variable letter further along the alphabet but I dont know in which direction :-
Any help appreciated ..thanks
This is completely untested, but I'm assuming that you can utilise the /Node option of WMIC:
#Echo Off
For /F "UseBackQ Delims=" %%Z In ("%~dp0hostnames.txt"
) Do For /F "UseBackQ Skip=1 Delims=" %%X In (`WMIC /Node:'%%~Z' Path^
Win32_UserProfile Where "Special='False'" Get LocalPath`
) Do For /F "Delims=" %%Y In ("%%X") Do Call :Sub "%%~Z" %%Y
Exit/B
:Sub
For /F "Tokens=1* Delims=:\" %%V In ("%~2") Do For %%U In (Folder1 Folder_2
) Do If Exist "\\%~1\%%~V$\%%~W\AppData\Local\%%~U"^
RD/S/Q "\\%~1\%%~V$\%%~W\AppData\Local\%%~U"
GoTo :EOF
Here is a way to do it in PowerShell. When you are confident that the correct directories will be removed, remove the -WhatIf switch from the Remove-Item command.
$dirlist = 'dir1', 'dir2'
$userdirs = (Get-CimInstance -ClassName Win32_UserProfile -Filter "Special=$false").LocalPath
foreach ($ud in $userdirs) {
foreach ($d in $dirlist) {
if (Test-Path -Path "$ud\$d") {
Remove-Item -Path "$ud\$d" -Recurse -WhatIf
}
}
}
Using Invoke-Command will allow you to run the script on all computers simultaneously. This assumes that the previous script was saved as udscan.ps1.
Invoke-Command -ComputerName 'host1', 'host2' -FilePath .\udscan.ps1
i have a folder and it contains hundreds of text file, i want to rename it .
file names ABCD01%%.txt or CAT9999&#.txt OR FILENAME2345&^$.txt
i want to rename file such that anything that comes between 'numbers' and '.txt' should be removed
for example
ABCD01%%.txt becomes ABCD01.txt
CAT9999&#.txt becomes CAT9999.txt
FILENAME2345&^$.txt becomes FILENAME2345.txt
Code so far:
#echo off
for /f "tokens=*" %%f in ('dir /l /a-d /b *.txt') do (
for /f "tokens=1 delims=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" %%n in ("%%~nf") do (
echo File: %%~nxf = value %%n
rename %%~nxf *%%n.txt
)
)
Another solution i get for linux is rename 's/[^a-zA-Z0-9_]//g' *.txt , i tried to port it for windows but i cant .. how can the above command be ported to windows (batch)
Assuming there are no duplicate renames and assuming that only letters and numbers make up the first part of the filename, the following code will rename the files. When you are satisfied that the renaming is being done correctly, remove the -WhatIf from the Rename-Item command.
Get-ChildItem -File -Filter '*.txt' |
Where-Object { $_.Name -match '([A-Za-z0-9]*).*\.txt' } |
ForEach-Object { Rename-Item $_.FullName "$($matches[1]).txt" -WhatIf }
If you are not running in PowerShell, put the code into a renfunc.ps1 file and invoke it from the cmd .bat script.
powershell -NoProfile -File 'renfunc.ps1'
I've encountered a few problems with escaping characters, I had to use a slightly different method. This script should work:
setlocal enabledelayedexpansion
for %%f in (*.txt) do (
set name=%%~nf
for /f "delims=0123456789 tokens=2" %%r in ("%%~nf") do set replace=%%r
set "replace=name:!replace:^^=!="
for /f %%x in ("!replace!") do set replace=!%%x!
ren "!name!.txt" "!replace!.txt"
)
EDIT: This revised script looks for the last numbers in the file name. [Don't mind the errors, they don't have any effect on the actual renaming.]
setlocal enabledelayedexpansion
for %%f in (*.txt) do (
set name=%%~nf
set p=0
for /l %%# in (2 1 32) do (
for %%e in ("!name:~-%%#,1!") do (
echo.%%~e|findstr /r /i "[0-9]"&&if !p!==0 set /a p=%%#-1
)
)
set "new=name:~,-!p!"
for %%e in ("!name:~-1!") do echo.%%~e|findstr /r /i "^[0-9]"&&set new=name
for /f %%x in ("!new!") do ren "!name!.txt" "!%%~x!.txt"
)
EDIT: Revised again for the special case of "&&". Delayed expansion within a for-loop can be tedious. Now the characters won't break syntax anymore (which means the errors that were to be ignored have ceased).
I'm try to find, in only one row, the number of files (*.rar) in a directory.
For doing this I'm using the commands:
for /f "delims=" %i in ('find /c ".rar" "D:\backup e ckpdb ept-icd\test\unload\lista_files_rar.txt"') do echo %i
but the value of %i I have at the end is : D:\BACKUP E CKPDB EPT-ICD\TEST\UNLOAD\LISTA_FILES_RAR.TXT: 8
I would like to obtain only the number 8 so instead to echo the value I would assign the value to a variable.
I use the command line : dir /b *.rar | find /c ".rar"
that it returns the value of rar files in the directory, but I can't assign the value to a variable, for example: dir /b *.rar | find /c ".rar" | set/a files =
I tried also to use the keyword tokens=2 but it doesn't work
p.s If it possible to do it only with the find command is also better
See here for example on counting files
Or you can simply do something like this (not tested)
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
This returns just the number; there might be a cleaner way to do it, but unfortuantly "find" can't take it's input from a pipe (i.e., I can't do dir | find):
#echo off
dir /b *.rar> out.tmp
for /f "usebackq tokens=3" %%i in (`find /c "rar" out.tmp`) do echo %%i
del out.tmp
Try "delims=: tokens=3"
You normally will have two colons in the result, one after the drive letter and one before the number you want, so your number should be token 3
Thank you, I think I will use
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
user135127
In this way I think also if somethink in the name of the dir the result should remain always the same.
which is the difference between :
dir /B *.rar ^| find /C /V "" and
dir /B *.rar ^| find /C ".rar" ?
for /f %a in ('dir "*.txt" ^| find "File(s)"') do set Count=%a
Gives
set Count=36
or you can use an arithmetic set and delayed environment variable expansion
set count=0
for %a in (*.txt) do #set /a Count=!Count!+ 1 > nul
echo %count%
gives
Count=36