0

We are in the process of moving to OneDrive for Business. To store files in OneDrive you can't have the following charactes in the filename: /:*?"<>|#% Additionally, a file name that begins with a tilde (~) isn't supported. I would like to search and replace the special character with a dash. Anyone have a batch file or powershell script?

cwhitmore
  • 37
  • 7
  • 1
    Please be aware that there are other rules for OneDrive filenames than invalid characters so simply replacing characters is, in general, not sufficient. Consult [Invalid Filename Check](http://stackoverflow.com/q/18494401/). – Dour High Arch Feb 02 '15 at 22:35
  • Dour - I appreciate the response, but I'm not sure how that post relates. Here is the actual page from Microsoft explaining filename limitations. https://support.microsoft.com/kb/2933738 – cwhitmore Feb 02 '15 at 23:03
  • FYI, one problem I've encountered in the past is name clashes, whereby the script alters a file and the new name matches an existing file. My preferred approach these days is to have the script report any bad names, and let a person deal with it. – DeanOC Feb 03 '15 at 02:00

1 Answers1

2

Coincidentally, \ / : * ? " < > | aren't allowed in Windows filenames either, so most of your list is already a non-issue. Assuming that list of characters is complete, all that remain are hashes, percents, and leading tildes.

@echo off
setlocal

:: replace ~ only if first char of filename
for %%I in ("~*") do (
    set "file=%%~I"
    setlocal enabledelayedexpansion
    echo %%~I -^> -!file:~1!
    ren "%%~I" "-!file:~1!"
    endlocal
)

:: replace # or % everywhere in filename
for %%d in (# %%) do (
    for %%I in ("*%%d*") do (
        set "file=%%~I"
        setlocal enabledelayedexpansion
        echo %%~I -^> !file:%%d=-!
        ren "%%~I" "!file:%%d=-!"
        endlocal
    )
)

But as Dour points out, this only fixes some of the problems. Your file uploads might still require some hand-holding. Or who knows? This could solve all your worldly problems. shrug


Edit: O.P. asked about adding /r to the for loops to make the replacements recursive. You could do that with a few tweaks, but you'll end up looping through the file list 3 times -- once for each symbol you're replacing. I suggest this would be a more efficient approach:

@echo off
setlocal enabledelayedexpansion

if "%~1"=="" goto usage
if not exist "%~1" goto usage
pushd "%~1"

for /r %%I in (*) do (
    set "file=%%~nxI"
    if "!file:~0,1!"=="~" (
        set "file=-!file:~1!"
    )
    for %%d in (# %%) do (
        if not "!file!"=="!file:%%d=!" (
            set "file=!file:%%d=-!"
        )
    )
    if not "!file!"=="%%~nxI" (
        echo %%~fI -^> !file!
        ren "%%~fI" "!file!"
    )
)

goto :EOF

:usage
echo Usage: %~nx0 pathname
echo To operate on the current directory, use a dot as the pathname.
echo Example: %~nx0 .

Edit 2: Added argument syntax.

Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
  • Thanks rojo. It works great at the current folder so I tried adding /r after "for" to recurse the subfolders. It seems to find the files, but says the syntax is incorrect. – cwhitmore Feb 03 '15 at 23:20
  • @cwhitmore try the updated tweaks and see what happens. – rojo Feb 03 '15 at 23:30
  • rojo - That worked great and didn't clobber my bang symbols. I added the following to allow this to run against different directories; %myvar% pushd %myvar% It works fine, but is there a way to require a variable so the batch file won't run unless it's specified? – cwhitmore Feb 04 '15 at 14:34
  • @cwhitmore Great! If my answer helped you, please consider marking it as accepted. [See this page](http://meta.stackexchange.com/q/5234/275822) for an explanation of why this is important. – rojo Feb 04 '15 at 14:35
  • Oops, had to edit my response. See above. – cwhitmore Feb 04 '15 at 14:37
  • @cwhitmore You mean require an argument, like `batfile.bat c:\path\to\run`? – rojo Feb 04 '15 at 14:41
  • Yes. I'd like the argument to be required. – cwhitmore Feb 05 '15 at 14:55
  • @cwhitmore added. If you have any additional feature requests, you should post a new question. But it would be a good idea to describe what effort you have made to find the solution to your question, and say where you're getting stuck. For now, glad I could help! – rojo Feb 05 '15 at 15:08
  • I got this working below, but after it runs it takes me to the directory that I passed in argument. How do I stay at directory where I started? @@echo off IF [%1]==[] goto Continue pushd %1 setlocal enabledelayedexpansion for /r %%I in (*) do ( set "file=%%~nxI" if "!file:~0,1!"=="~" ( set "file=-!file:~1!" ) for %%d in (# %%) do ( if not "!file!"=="!file:%%d=!" ( set "file=!file:%%d=-!" ) ) if not "!file!"=="%%~nxI" ( echo %%~fI -^> !file! ren "%%~fI" "!file!" ) ) Exit /B :Continue @echo Enter directory – cwhitmore Feb 05 '15 at 15:16
  • Move the `setlocal enabledelayedexpansion` line below `pushd` and replace `pushd` with `cd`. You should really keep the quotes in the `if` statement, rather than brackets. `if "%~1"=="" goto Continue`. If you have spaces in the path name, the bracket notation will break. – rojo Feb 05 '15 at 15:25
  • How do I format code? I tried using {} and selecting code and hitting CTRL K – cwhitmore Feb 05 '15 at 15:26
  • It's done with a `<-- language: lang-js -->` meta tag. [See this page](http://meta.stackexchange.com/a/79591/275822) for details. There's no prettify library for dos / batch, but js does pretty well. If you're talking about `formatting code within comments`, just surround your code with backticks (the `\`` character). – rojo Feb 05 '15 at 15:30
  • If I change pushd to cd it won't check subdirectories, but it does stay in same directory I run the script from. – cwhitmore Feb 05 '15 at 15:40
  • Post a new question with your current code. – rojo Feb 05 '15 at 15:41