DOS Batch / XP Command prompt file rename to remove spaces.

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
jaffamuffin
Posts: 40
Joined: 25 Jan 2008 14:05

DOS Batch / XP Command prompt file rename to remove spaces.

#1 Post by jaffamuffin » 25 Jan 2008 14:23

Hi all

Does anyone have a script or algorithm for searching through a directory tree of files and renaming any that have spaces in the file names and directory names? e.g. to have a _ instead of a space. Most files won't have a space.

The code below does it but it's not great and it's slow (when you're checking 50,000+ files) and I know there must be a better way. I have unixutils binaries, and confirmation or failure of the operation is required, as the rest of my scripts can't proceed unless the files are renamed properly.


Code: Select all

@echo off
REM %1 is top level of dir heirachy to be checked e.g. c:\checkthesefiles\
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION::REMOVE SPACES FROM FILES NAMES

SET UNTMP=C:\UNTMP\
if not exist !UNTMP! MKDIR !UNTMP!


::check for spaces
DIR %1 /B /S | grep "\ ">nul
IF NOT ERRORLEVEL 1 SET ERRNONE=TRUE
IF !ERRNONE!==TRUE (
   ECHO [WW] Filenames containing Spaces were found - Removing spaces...
   FOR /R %1 %%G IN (.) DO ECHO !CD! & CALL :spaceRemove "%%G"
   ECHO.[II] SPACES SUBSTITUTED FOR UNDERSCORES...COMPLETE!
) ELSE (
   ECHO [II] No spaces in filename found.
)

GOTO:EOF

:spaceRemove
SET SUBDIRLISTORIG=!UNTMP!SUBDIRLISTORIG.TXT
SET SUBDIRLISTNEW=!UNTMP!SUBDIRLISTNEW.TXT
SET SUBDIRLISTCOMB=!UNTMP!SUBDIRLISTCOMB.TXT

CD /D %1
DIR /ON /B > !SUBDIRLISTORIG!
DIR /ON /B | sed "s/ /_/g" > !SUBDIRLISTNEW!
paste -d, !SUBDIRLISTORIG! !SUBDIRLISTNEW! > !SUBDIRLISTCOMB!
FOR /F "tokens=1,2 delims=," %%G IN (!SUBDIRLISTCOMB!) DO (
   IF EXIST "%%G" (
      REM DIR,OLDNAME,NEWNAME
      REM ECHO !CD!,%%G,%%H >> !UNTMP!RENAMELOG.TXT
         REN "%%G" %%H
      REM
   ) ELSE (
      ECHO [EE] ERROR FILE DON'T EXIST
      GOTO:error3 "%%G"
   )
)
GOTO:EOF

DosItHelp
Expert
Posts: 239
Joined: 18 Feb 2006 19:54

#2 Post by DosItHelp » 30 Jan 2008 22:53

jaffamuffin,

This should do the trick

Code: Select all

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CD /D "%~1"
for /f "delims=" %%A in ('dir /b /s') do (
    set "f=%%~A"
    set "f=!f: =_!"  &rem replace space with underscore
    if "%%~A" NEQ "!f!" echo ren "%%~A" "!f!"
)


DOS IT HELP :wink:

jaffamuffin
Posts: 40
Joined: 25 Jan 2008 14:05

#3 Post by jaffamuffin » 31 Jan 2008 18:17

Thanks!


Unfortunately though, that runs into similar problems,

1. It starts to rename the top level dirs before the subdirs. Once it does this it can't find the subdirs and errors.

2. the REN command is too weak for this, you can't rename a file including path to another file including path.(or can you?) The original script above Cds into each dir and perfoms the ren on each file there.

Plus, this seemed to remove spaces in the whole path right back to drive letter, %1 should be the root for this operation.

However the script is very useful and I took it and changed it to this:

Code: Select all

@ECHO OFF 
SETLOCAL ENABLEDELAYEDEXPANSION
REM directories first - must sort as renaming a top level dir makes the sub dirs inaccessible
CD /D "%~1"
for /f "delims=" %%A in ('dir /AD /b /s ^| sort /r') do (
    set "f=%%~nA"
    set "g=%%~A"
    set "f=!f: =_!"  &rem replace space with underscore
    cd /d "%%~A" & cd ..
    if "%%~A" NEQ "!~g!" REN "%%~nA" "!f!"
)

REM Files second
CD /D "%~1"
for /f "delims=" %%A in ('dir /A-D /b /s') do (
     set "f=%%~nxA"
     set "g=%%~A"
     set "f=!f: =_!"  &rem replace space with underscore
     cd /d "%%~dpA"
     if "%%~A" NEQ "!~g!" REN "%%~A" "!f!"
)



This seems to work well for me... Could it be tidied in a way?


I just tested on a bunch of New Folders and New Text Documents.txt nested a few times in each other in a single grandparent directory.

DosItHelp
Expert
Posts: 239
Joined: 18 Feb 2006 19:54

#4 Post by DosItHelp » 31 Jan 2008 21:58

jaffamuffin,

I see your point. Smart move of you to just reverse the output list. :wink:
Well since after reversing the order you move your way bottom up, it should be ok to rename the directories in the same loop, because if you hit a directory then for sure you have already processed its content, right?
So how about this:

Code: Select all

SETLOCAL ENABLEDELAYEDEXPANSION
CD "C:\Web\_Material\tmp"||GOTO:EOF
for /f "delims=" %%A in ('"dir /b /s|sort /r"') do (
    set "f=%%~nxA"
    set "f=!f: =_!"  &rem replace space with underscore
    if "%%~nxA" NEQ "!f!" (
        echo.cd "%%~dpA"
        echo.ren "%%~nxA" "!f!"
    )
)

:)
Last edited by DosItHelp on 20 Feb 2009 22:21, edited 2 times in total.

jaffamuffin
Posts: 40
Joined: 25 Jan 2008 14:05

#5 Post by jaffamuffin » 01 Feb 2008 15:48

Yep, well done :)

Didn't know about using the double quotes to eliminate the caret before the pipe. Does this technique require the use of "delims=" ?

I took this and changed it into a bit more flexible will take search and replace params and will do files, dirs or both.

Code: Select all

@echo off
REM %4- PATH TO SEARCH FROM
REM %2 - "TEXT TO FIND"
REM %3 - "TEXT TO REPLACE WITH"
REM %1 - -both OR  -files OR -dirs
REM example   -   replace.bat -files new old C:\tmp   -- Will replace old with new in all filenames in c:\tmp and below
SETLOCAL ENABLEDELAYEDEXPANSION
SET MODE=%~1
SET FIND=%~2
SET REPLACE=%~3

CD /D "%~4"||GOTO:EOF

rem default is rename only files
SET ACTION=NOTFOUND
IF %MODE%==-both SET ACTION="dir /b /s|sort /r"
IF %MODE%==-dirs SET ACTION="dir /b /s /ad|sort /r"
IF %MODE%==-files SET ACTION="dir /b /s /a-d|sort /r"
if %ACTION%==NOTFOUND ECHO Please select -both, -files, or -dirs & goto:eof

for /f "delims=" %%A in ('%ACTION%') do (
    set "f=%%~nxA"
    set "f=!f:%FIND%=%REPLACE%!"  &rem find and replace
    if "%%~nxA" NEQ "!f!" (
        cd "%%~dpA"
        ren "%%~nxA" "!f!"
    )
)

GOTO:EOF

DosItHelp
Expert
Posts: 239
Joined: 18 Feb 2006 19:54

#6 Post by DosItHelp » 01 Feb 2008 21:37

Awesome :wink:

budi.com
Posts: 2
Joined: 16 Dec 2011 04:34

Re: DOS Batch / XP Command prompt file rename to remove spac

#7 Post by budi.com » 16 Dec 2011 04:39

you guys are awesome. i have no clue how to read the codes. i stumbled upon this page trying to find a simple drophere.bat file that i can use to drop a couple of files in order to rename the underscores within the filenames to "-"

eg. abc_def.txt to abc-def.txt

or a simple runthis.bat that will do the rename for all the files in the same folder as the runthis.bat

i hope you gents can point me in the right directions

have a pleasant holiday

jaffamuffin
Posts: 40
Joined: 25 Jan 2008 14:05

Re: DOS Batch / XP Command prompt file rename to remove spac

#8 Post by jaffamuffin » 16 Dec 2011 10:10

My script above will do that. Paste it into a file called replace.bat. Then

replace.bat -files new old C:\tmp

i.e:

Replace.bat -files "-" " " c:\filestorename\

jaffamuffin
Posts: 40
Joined: 25 Jan 2008 14:05

Re: DOS Batch / XP Command prompt file rename to remove spac

#9 Post by jaffamuffin » 16 Dec 2011 10:12

Oops for underscore to hyphen you want

replace.bat -files "-" "_" C:\files\to\rename


Or maybe the other way.. Damn looks like ive mixed the old and new up in the example ?

budi.com
Posts: 2
Joined: 16 Dec 2011 04:34

Re: DOS Batch / XP Command prompt file rename to remove spac

#10 Post by budi.com » 17 Dec 2011 10:42

thanks jaffamuffin. i'll give it a spin

dbenham
Expert
Posts: 2378
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: DOS Batch / XP Command prompt file rename to remove spac

#11 Post by dbenham » 18 Dec 2011 09:29

Nice script :D

I've made a few improvements, some more important than others:

1) The original will corrupt any renamed file/dir that contains ! in the name. That character is not seen often, but you may be sorry if you happen to run into one and use the original code :!: The problem is the expansion of the FOR variable when delayed expansion is enabled. I postpone enabling delayed expansion and toggle it on and off within the loop. I needed to create a few more vars to compensate.

2) The rename can fail if the new name already exists (duplicate) or if the name is empty after the substitution. The REN command gives an error message, but doesn't tell you what file/dir failed. I simply added a message indicating the failed file/dir that only fires upon failure.

3) I improved the argument parsing code at the top to support special characters like & or ^. The original would prevent you from replacing "&" with "_and_".

I haven't tested these changes :!: I'm sure the concepts of the fixes are correct, but I may have introduced a bug, so test carefully.

Code: Select all

@echo off
REM %4- PATH TO SEARCH FROM
REM %2 - "TEXT TO FIND"
REM %3 - "TEXT TO REPLACE WITH"
REM %1 - -both OR  -files OR -dirs
REM example   -   replace.bat -files new old C:\tmp   -- Will replace old with new in all filenames in c:\tmp and below
SETLOCAL DisableDelayedExpansion
SET "MODE=%~1"
SET "FIND=%~2"
SET "REPLACE=%~3"

CD /D "%~4"||GOTO:EOF

rem default is rename only files
SET ACTION=NOTFOUND
IF "%MODE%"=="-both" SET ACTION="dir /b /s|sort /r"
IF "%MODE%"=="-dirs" SET ACTION="dir /b /s /ad|sort /r"
IF "%MODE%"=="-files" SET ACTION="dir /b /s /a-d|sort /r"
if %ACTION%==NOTFOUND ECHO Please select -both, -files, or -dirs & goto:eof

for /f "delims=" %%A in ('%ACTION%') do (
    set "f=%%~nxA"
    set "p=%%~dpA"
    setlocal enableDelayedExpansion
    set "f2=!f:%FIND%=%REPLACE%!"  &rem find and replace
    if "!f2!" NEQ "!f!" (
        cd "!p!"
        ren "!f!" "!f2!" || echo Unable to rename "!p!!f!"
    )
    endlocal
)

GOTO:EOF


Dave Benham

Post Reply