<http://www.netikka.net/tsneti/info/tscmd166.htm>
Copyright © 2003-2012 by Prof. Timo Salmi  
Last modified Tue 17-Jul-2012 07:29:59

 
Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index
 

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.



166} Substituting spaces with underscores in a folder's file names.

"Please, does anyone have a script I can run the a command prompt that will cycle thru the files in the current directory and rename files with spaces to files with _?"

There may be more concise ways, but this is more generic and more tolerant of the potential poison characters.
  @echo off & setlocal enableextensions
  set targetFolder=C:\Whatever
  pushd "%targetFolder%"
  for /f "tokens=*" %%f in ('
    dir /b /a-d-s "%targetFolder%\* *.*"') do (
      call :ProcessOneFile "%%~ff")
  popd
  endlocal & goto :EOF
  ::
  :ProcessOneFile
  setlocal enableextensions disabledelayedexpansion
    set filename="%~nx1"
    set filename=%filename: =_%
    echo ren %1 %filename%
  endlocal & goto :EOF

The output might look something like
  ren "C:\Whatever\My test file.txt" "My_test_file.txt"
  ren "C:\Whatever\My test file2.txt" "My_test_file2.txt"
  ren "C:\Whatever\Test & (5!).txt" "Test_&_(5!).txt"
1) The pushd/popd-pair ensures that the file path is correct when the /b switch is used in the dir. (Else it will be the script's, which might be different.)
2) The /a-d switch sees to not renaming folders.
3) Remove the echo when you are sure that the solution is what you want.

A more condensed, slightly cryptic solution:
  @echo off & setlocal enableextensions
  set targetFolder=C:\Whatever
  pushd "%targetFolder%"
  for /f "tokens=*" %%f in ('
    dir /b /a-d-s "%targetFolder%\* *.*"') do (
      set "_=%%~nxf"
      call echo ren "%%~ff" "%%_: =_%%"
      )
  popd
  endlocal & goto :EOF

A much trickier situation arises if we wish to replace the dots ( . ) in a file name with underscores ( _ ). With the natural exception of the one preceding the file's extension. Such a task is best handled with a Visual Basic Script (VBScript) aided command line script.
  @echo off & setlocal enableextensions
  set targetFolder=C:\_M
  ::
  :: Build a Visual Basic Script

  set vbs_=%temp%\tmp$$$.vbs
  >"%vbs_%" findstr "'%skip%VBS" "%~f0"
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6

  cscript //nologo "%vbs_%" "%targetFolder%"
  ::
  :: Clean up

  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  '

  Set arg = WScript.Arguments 'VBS
  Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
  Set f = fso.GetFolder(arg(0)) 'VBS
  Set fc = f.Files 'VBS
  For Each f1 in fc 'VBS
    basename = fso.GetBaseName(f1) 'VBS
    If InStr (basename, ".") Then 'VBS
      extension = fso.GetExtensionName(f1) 'VBS
      s = "rem @ren " & Chr(34) & arg(0) & "\" 'VBS
      s = s & basename & "." & extension & Chr(34) 'VBS
      newbasename = Replace(basename, ".", "_") 'VBS
      s = s & " " & Chr(34) & newbasename 'VBS
      s = s & "." & extension & Chr(34) 'VBS
      Wscript.Echo s 'VBS
    End If 'VBS
  Next 'VBS

Given
  C:\_M>dir /a:-d /b
  My test file.txt
  My.&(!).test.txt
  This.is.a.test.txt

The safety output would be
  C:\_M>c:\_d\test\cmdfaq
  rem @ren "C:\_M\My.&(!).test.txt" "My_&(!)_test.txt"
  rem @ren "C:\_M\This.is.a.test.txt" "This_is_a_test.txt"

I receive mainframe files and I'm trying to remove the extra periods in the filename since my script isn't picking them up. Or even replacing the periods with "_" like FC.HIST.20080910.TXT to FC_HIST_20080910.TXT

P.S. I'd prefer DOS commands for this. Please no VBS, etc.

First off, as seen in the above it would be the most robust and flexible way. Nevertheless:

As you will have observed, there have been several interesting suggestions to your question in the alt.msdos.batch newsgroup. However, I would be very careful with the direct ren one- liners. It is very easy to tangle the names hopelessly because of the circularity danger. Much safer to take the more cautions slightly more cumbersome route. But if you still prefer the ren one-liners, at the very least first back up your files, or apply those solutions on a copied set.

If you do not have poison characters in your file names, here is one prudent pure-batch approach demonstrated
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  set targetFolder=C:\_M\TEST
  ::
  :: Make a test file set

  if not exist "%targetFolder%\" mkdir "%targetFolder%"
  >"%targetFolder%\FC.HIST.20080910.TXT" echo Test file 1
  >"%targetFolder%\FC.HIST.20080930.TXT" echo Test file 2
  >"%targetFolder%\FC.HIST.20081001a.TXT" echo Test file 3
  >"%targetFolder%\My test file.txt" echo Test file 4
  dir "%targetFolder%"
  echo.
  ::
  pushd "%targetFolder%"
  for /f "tokens=*" %%f in ('
    dir /b /a-d-s "%targetFolder%\*.txt"') do (
      call :ProcessOneFile "%%~ff")
  popd
  endlocal & goto :EOF
  ::
  :ProcessOneFile
  setlocal enableextensions disabledelayedexpansion
    set basename=%~n1
    set basename=%basename:.=_%
    set filename=%basename%%~x1
    echo ren %1 "%filename%"
  endlocal & goto :EOF

The output would be

C:\_D\TEST>cmdfaq
 Volume in drive C is
 Volume Serial Number is

 Directory of C:\_M\TEST

04.10.2008  21:20                13 FC.HIST.20080910.TXT
04.10.2008  21:20                13 FC.HIST.20080930.TXT
04.10.2008  21:20                13 FC.HIST.20081001a.TXT
04.10.2008  21:20                13 My test file.txt
               4 File(s)             52 bytes
               0 Dir(s)  229,559,308,288 bytes free

ren "C:\_M\TEST\FC.HIST.20080910.TXT" "FC_HIST_20080910.TXT"
ren "C:\_M\TEST\FC.HIST.20080930.TXT" "FC_HIST_20080930.TXT"
ren "C:\_M\TEST\FC.HIST.20081001a.TXT" "FC_HIST_20081001a.TXT"
ren "C:\_M\TEST\My test file.txt" "My test file.txt"

Should one wish to remove the underscore ( _ ) after HIST, substitute
  :ProcessOneFile
  setlocal enableextensions disabledelayedexpansion
    set basename=%~n1
    set basename=%basename:.=_%
    set basename=%basename:HIST_=HIST%
    set filename=%basename%%~x1
    echo ren %1 "%filename%"
  endlocal & goto :EOF

References/Comments: (If a Google message link fails try the links within the brackets.)
  Google Groups 23 Sep 2008 20:29:57 +0100 [M]