I want to delete all the folders with only digit name.
So I write a batch file using regular expression:
#echo off
D:
cd D:\Install\Work
for /d %%i in (*|findstr "^[0-9]*$") do (
rd /s /q %%i
)
echo [all the folders under work are deleted!]
pause
but it doesnt work. Where is the error?
#ECHO OFF
SETLOCAL
FOR /f %%x IN (
'dir /ad /b * ^|FINDSTR "^[0-9]*$" '
) DO ECHO %%x
FOR /F reads lines from a file/command output to the metavariable.
for /d simply applies dirnames to the metavariable.
Try this:
#echo off
for /r D:\Install\Work %%d in (.) do (
echo %%~nxd|findstr "^[0-9]*$" >nul && rd /s /q "%%~fd"
)
Note that this will delete all-digit folders even if they contain other folders with names not consisting of only digits!
%%~nxd: remove enclosing double quotes from %%d (~) and expand name (n) and extension (x) only
>nul: suppress output on STDOUT
%%~fd: remove enclosing double quotes from %%d (~) and expand full path (f)
Related
With a bat file I sorted the subfolders list in a Directory but what are the 2 folders named "." 1 dot and ".." 2 dots ? actually they are not present in windows explorer and most of all how I can avoid to show them in the list ?
#echo off
setlocal EnableExtensions EnableDelayedExpansion
> ".\Utils\Check last modified Profile.txt" (
for /F "delims=" %%D in ('
dir %APPDATA%\Mozilla\Firefox\Profiles\ /A /all-D /TW /A:D /O:-DE
') do (
rem print each item:
echo %%~D %
)
)
endlocal
image here > https://imgur.com/8XyQk6q
dir %APPDATA%\Mozilla\Firefox\Profiles\ /A /all-D /TW /A:D /O:-DE ^|findstr /v /e /L /c:"."
worked for me.
The dir output is sent to findstr which allows through lines which do not (/v) end (/e) with the literal (/L) string "."
Directories cannot be created that end with .
I believe I do not need to comment further on the attributes-selection specification.
The ^ is required to have the pipe applied to the dir command, not the for.
I'll make no further comment on the attributes-selection specified.
. is the current directory. .. is it's parent directory.
Explorer hides them.
Dir C:\windows\.\.\..
I have decided to post this because the existing answers appear to be using the same crazy and incorrect options for the Dir command. The following examples use the appropriate findstr.exe method of eliminating the . and .. directory entries from your listing, sorted according to most recently modified to least recent. I have included the full path to findstr.exe to eliminate the possibility of %PATH% and/or %PATHEXT% modifications from not being able to locate it.
If you wanted the same output format, then this should work for you:
#For /F "Tokens=1*Delims=:" %%G In ('"Dir "%AppData%\Mozilla\Firefox\Profiles" /AD/O-DE 2>NUL|%SystemRoot%\System32\findstr.exe /ELNV ".""')Do #Echo(%%H
If you don't need the empty lines then, this should omit those for you:
#For /F "Delims=" %%G In ('"Dir "%AppData%\Mozilla\Firefox\Profiles" /AD/O-DE 2>NUL|%SystemRoot%\System32\findstr.exe /ELV ".""')Do #Echo %%G
And if you only needed the directory name lines, then perhaps this will satisfy you:
#For /F EOL^=^ Delims^= %%G In ('"Dir "%AppData%\Mozilla\Firefox\Profiles" /AD/O-DE 2>NUL|%SystemRoot%\System32\findstr.exe /ELV ".""')Do #Echo %%G
You can use and add this switch /B
#echo off
#for /F "delims=" %%D in ('
dir %APPDATA%\Mozilla\Firefox\Profiles\ /A /all-D /TW /A:D /O:-DE /B
') do (
echo %%~D
)
I have a file name
pp-sssss-iiii-12.0.111.22_31-i-P.0.16.1.1
I want from the name only this (output desired):
12.0.111.22_31
then replace . with 0 and remove '_' so I got the below
1200011102231
well I tried to start from something like this
cd %cd%
for %%F in (*.txt) do echo %%~nxF >>1.txt
but I didnt know how to continue
edit , the code :
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=C:\Users\moudiz\Desktop\new folder\tttt"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.pbd" '
) DO (
FOR /f "tokens=4delims=-" %%d IN ("%%a") DO (
SET "modname=%%d"
SET "modname=!modname:.=0!"
SET "modname=!modname:_=!"
ECHO %%a becomes !modname!
)
)
GOTO :EOF
pause
the name of the file
P-Script-LogFiles-1.0.33.33_123-IB-P.0.16.357.1.pbd
the output 100033033123
[note: OP belatedly asked for the first token of the name to be prepended to the name generated from the original post, hence use of %%c below]
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.txt" '
) DO (
echo File "%%a"
FOR /f "tokens=1,4delims=-" %%c IN ("%%a") DO (
SET "modname=%%d"
SET "modname=!modname:.=0!"
SET "modname=!modname:_=!"
ECHO %%a becomes %%c!modname!
)
pause
)
pause
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Using delayedexpansion, !var! refers to the modified value of the variable and set "var=!var:string=gnirts!" substitutes "gnirts" for "string" invarand assigns the result back tovar`.
Now - quite what you want to do with this modified result, you don't reveal - but guessing at renaming,
echo ren "%%a" "!modname!"
should be usable
To prepend the first token, simply change the tokens= to 1,4 *to select the first and fourth tokens) - and change the metavariable in the for to %%c (in order that the %%d processing remains the same), then use %%c which will contain the portion of the original filename before the first -.
I have a directory structure containing home directories named after the users full name (ForenameSurname), like:
/user/JohnDoe
/user/JaneDoe
/user/MobyDick
Now i want to copy the whole structure, changing ForenameSurname to "'first two letters of first name'+'surname'", resulting:
/user/JoDoe
/user/JaDoe
/user/MoDick
I know how to get substrings (~n), but how to split a string on the first capital letter? Is it possible at all using pure batch?
#echo off
setlocal enableextensions enabledelayedexpansion
set "root=%cd%\users"
for /d %%f in ( "%root%\*" ) do (
set "name=%%~nxf"
for /f %%a in ("!name:~0,2!"
) do for /f "tokens=* delims=abcdefghijklmnopqrstuvwxyz" %%b in ("!name:~2!"
) do if not "%%~nxf"=="%%~a%%~b" if not exist "%root%\%%~a%%~b" (
echo ren "%%~ff" "%%~a%%~b"
) else (
echo "%%~nxf" can not be renamed to "%%~a%%~b"
)
)
Rename operations are only echoed to console. If the output is correct, remove the echo that prefixes the ren command.
Try this:
#echo off
setlocal EnableDelayedExpansion
set "upcaseLetters=ABCDEFGHIJKLMNOPQRSTUVWXYZ"
cd \user
for /D %%a in (*) do (
call :convert name=%%a
echo New name: !name!
)
goto :EOF
:convert
set "var=%2"
:nextChar
set "char=%var:~2,1%"
if "!upcaseLetters:%char%=%char%!" equ "%upcaseLetters%" goto end
set "var=%var:~0,2%%var:~3%"
goto nextChar
:end
set "%1=%var%"
exit /B
I would use my JREN.BAT regular expression rename utility - a hybrid JScript/batch script that runs natively on any Windows machine form XP onward.
jren "^([A-Z][a-z])[a-z]*(?=[A-Z])" $1 /d /t /p c:\users
The /T option is test mode, meaning it only displays the proposed rename results. Remove the /T option to actually rename the folders.
Im looking for a batch script to (recursively) rename a folder of files..
Example of the rename:
34354563.randomname_newname.png to newname.png
I already dug up the RegEx for matching from the beginning of the string to the first underscore (its ^(.*?)_ ), but cant convince Windows Batch to let me copy or rename using RegEx.
From command-line prompt - without regex:
FOR /R %f IN (*.*) DO FOR /F "DELIMS=_ TOKENS=1,*" %m IN ("%~nxf") DO #IF NOT "%n" == "" REN "%f" "%n"
In batch file, double %:
FOR /R %%f IN (*.*) DO FOR /F "DELIMS=_ TOKENS=1,*" %%m IN ("%%~nxf") DO #IF NOT "%%n" == "" REN "%%f" "%%n"
EDIT: A new pure batch solution issuing following cases:
Path\File_name.ext => name.ext
Path\none.ext (does nothing)
Path\Some_file_name.ext => file_name.ext
Path\name.some_ext (does nothing)
Path\Some_file_name.some_ext => name.some_ext
Batch (remove ECHO to make it functional):
FOR /R %%f IN (*.*) DO CALL :UseLast "%%~f" "%%~nf"
GOTO :EOF
:UseLast
FOR /F "DELIMS=_ TOKENS=1,*" %%m IN (%2) DO IF "%%n"=="" (
IF NOT "%~2"=="%~n1" ECHO REN %1 "%~2%~x1"
) ELSE CALL :UseLast %1 "%%n"
GOTO :EOF
avoid _ in the extension:
#ECHO OFF
FOR /F "DELIMS=" %%A IN ('DIR /S /B /A-D *_*.*') DO FOR /F "TOKENS=1*DELIMS=_" %%B IN ("%%~NA") DO IF "%%~C" NEQ "" ECHO REN "%%~A" "%%~C%%~XA"
Look at the output and remove ECHO if it looks good.
The standard windows shell doesn't have regex capabilities, and in fact it's extremely basic. But you can use powershell to do this.
I'm not very familiar with power shell, but this other question explains how to filter files: Using powershell to find files that match two seperate regular expressions
New Solution
There is an extremely simple solution using JREN.BAT, my new hybrid JScript/batch command line utility for renaming files and folders via regular expression search and replace.
Only rename files with one underscore:
jren "^[^_]+_([^_]+\.png)$" "$1" /s /i
Preserve everything after the first underscore:
jren "^.*?_" "" /s /fm "*.png"
Preserve everything after the last underscore:
jren "^.*_" "" /s /fm "*.png"
=========================================================
Original Answer
This can be done using a hybrid JScript/batch utility called REPL.BAT that performs regex search and replace on stdin and writes the result to stdout. All the solutions below assume REPL.BAT is somewhere within your PATH.
I intentionally put ECHO ON so that you get a log of the executed rename commands. This is especially important if you get a name collision: two different starting names could both collapse to the same new name. Only the first rename will succeed - the second will fail with an error message.
I have three solutions that differ only in how they handle names that contain more than 1 _ character.
This solution will only rename files that have exactly one _ in the name (disregarding extension). A name like a_b_c_d.txt would be ignored.
#echo on&#for /f "tokens=1,2 delims=*" %%A in (
'2^>nul dir /b /s /a-d *_* ^| repl ".*\\[^_\\]*_([^_\\]*\.[^.\\]*)$" "$&*$1" a'
) do ren "%%A" "%%B"
The next solution will preserve the name after the last _. A name like a_b_c_d.txt would become d.txt
#echo on&#for /f "tokens=1,2 delims=*" %%A in (
'2^>nul dir /b /s /a-d *_* ^| repl ".*_([^\\_.]*\.[^.\\]*)$" "$&*$1" a'
) do echo ren "%%A" "%%B"
This last solution will preserve the name after the first _. A name like a_b_c_d.txt would become b_c_d.txt. This should give the same result as the Endoro answer.
#echo on&#for /f "tokens=1,2 delims=*" %%A in (
'2^>nul dir /b /s /a-d *_* ^| repl ".*\\[^\\]*?_([^\\]*\.[^.\\]*)$" "$&*$1" a'
) do echo ren "%%A" "%%B"
I'm trying to write a script that lists every file name in a specified folder, and notifies the user if that folder is empty. So far I've got:
for /r "O:\Mail\5-Friday" %%d in (*.pdf) do (
dir /a /b "%%~fd" 2>nul | findstr "^" >nul && echo %%~nd || echo Empty: Friday
)
but I've no idea where to put the if, else operators.
And is there a way to specify a folder based on user input without rewriting every function for each folder? So instead of:
if /i {%ANS%}=={thursday} (goto :thursday)
if /i {%ANS%}=={friday} (goto :friday)
:thursday
<do stuff>
:friday
<do the same stuff as thursday, but a different directory>
etc, I could write one function with variables in place of paths, assign the directory to a variable, and easily add/remove folders in the code as necessary?
To address the first part of your question, "where to put the if, else operators"... The notation of
command | findstr >nul && echo success || echo fail
... is shorthand for
command | findstr >nul
if ERRORLEVEL 1 (
echo fail
) else (
echo success
)
The magic that happens is in the conditional execution operators, the && and ||. If findstr exits with status zero, then a match was found. Therefore, execute the stuff after &&. Otherwise, status is non-zero, no match was found, so execute the stuff after ||. See how that works?
For the second part, here's a typical way to prompt the user to provide entry based on a finite number of choices.
#echo off
setlocal
:begin
set /p "day=What day? "
for %%I in (monday tuesday wednesday thursday friday) do (
if /i "%day%" equ "%%I" goto %%I
)
goto begin
:monday
call :getdirs "O:\Mail\1-Monday"
goto :EOF
:tuesday
call :getdirs "O:\Mail\2-Tuesday"
goto :EOF
:wednesday
call :getdirs "O:\Mail\3-Wednesday"
goto :EOF
:thursday
call :getdirs "O:\Mail\4-Thursday"
goto :EOF
:friday
call :getdirs "O:\Mail\5-Friday"
goto :EOF
:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
dir /b "%%I" 2>NUL | findstr "^" >NUL || echo %%I has no files
)
goto :EOF
Or, even hacksier, I'll do something you probably weren't expecting was possible. I'll have the script open a folder selection dialog to allow the user to select the directory to scan. It's a batch / JScript hybrid script.
If you wish, you can set the root of the folder browser to a ShellSpecialConstants folder by changing the last argument in the next-to-the-last line. Using a value of 0x11 makes the root your system's drives. No value or a value of 0x00 makes the root "Desktop". Or leave the script as-is to set the root as "O:\Mail".
#if (#a==#b) #end /*
:: fchooser2.bat
:: batch portion
#echo off
setlocal
set initialDir="O:\Mail"
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%initialDir%"') do (
call :getdirs "%%I"
)
exit /b
:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
dir /b "%%I" 2>NUL | findstr "^" >NUL || (
rem This is where you put code to handle empty directories.
echo %%I has no files
)
)
goto :EOF
:: JScript portion */
var shl = new ActiveXObject("Shell.Application");
var hint = 'Double-click a folder to expand, and\nchoose a folder to scan for empty directories';
var folder = shl.BrowseForFolder(0, hint, 0, WSH.Arguments(0));
WSH.Echo(folder ? folder.self.path : '');
Edit Since apparently BrowseForFolder accepts an absolute directory, there's really no benefit to using PowerShell / C#. The hybrid batch / PowerShell / C# script shall henceforth be retired to the revision history.
This is fun!