-3

say I have a set of files, batch script, and subdirectories "Numbers" and "NoNumbers" in a "Files" directory in Windows, like so:

<Files>
    <Numbers>
    <NoNumbers>
    updatefiles.bat
    Alpha.txt
    Alpha #306.txt
    Beta.txt
    Gamma.txt
    Gamma #402.txt
    Epsilon.txt
    Epsilon #862.txt

and I want to move all of the files containing #XXX into a subdirectory "Numbers" and all of the ones that do not contain #XXX into a subdirectory "NoNumbers"

After the move, I want to remove the last 4 characters of the files in the "Numbers" directory (eg. Alpha #306.txt renamed to Alpha.txt).

I also want to do all of this using relative paths (e.g. the "Files" directory may be anywhere on any Windows drive).

The end result would look like this:

<Files>
    <Numbers>
        Alpha.json
        Beta.json
        Gamma.json
        Epsilon.json
    <NoNumbers>
        Alpha.json
        Beta.json
        Gamma.json
        Epsilon.json

What would the easiest way to do this be with the batch script updatefiles.bat?

Thanks!

EDIT: Here are my initial attempts (tried to do it in pieces first):

Attempting to move the files containing # to subdirectory "Numbers"

ren *.txt *.json
for /f "eol=: delims=" %%F in ('dir /b^|find "#"') do move /Y "%%F" "Numbers"

Attempting to cut off the last 4 characters and .txt extension:

for %%i in ("*.txt") do (set fname=%%i) & call :rename
goto :eof
:rename
::Cuts off last 9 chars
ren "%fname%" "%fname:~0,-9%.json"
goto :eof

Now I need to combine those into one .bat that uses relative paths

EDIT 2: Here's what I've come up with as the combined script:

setlocal
ren *.txt *.json
for /f "eol=: delims=" %%F in ('dir /b^|find "#"') do move /Y "%%F" "Numbers"
for /f "eol=: delims=" %%G in ('dir /b^|find ".json"') do move /Y "%%G" "NoNumbers"
CD /D %~dp0\Numbers
for %%i in ("*.json") do (set fname=%%i) & call :rename
goto :eof
:rename
::Cuts off last 10 chars, then appends .json
ren "%fname%" "%fname:~0,-10%.json"
goto :eof

It renames the .txt to .json, moves all .json files that have "#" in them to the "Numbers" directory, moves everything else to the "NoNumbers" directory, changes to the "Numbers" directory, removes the last 10 characters of each file, and adds back the .json extension. I'm sure there's a more efficient way but it does what I need it to do now.

derHugo
  • 83,094
  • 9
  • 75
  • 115
Hayward
  • 21
  • 5
  • StackOverflow isn't a code-writing service. You should present your own initial attempts, and ask questions to identify bugs and issues. http://idownvotedbecau.se/noattempt/ – Derek Brown Nov 13 '17 at 17:55
  • Edited in my initial attempts, sorry! – Hayward Nov 13 '17 at 18:22
  • Since you've now posted code, the standout problem is that Batch is sensitive to spaces in a `SET` statement. `SET FLAG = N` sets a variable named "FLAG[Space]" to a value of "[Space]N". Since `fname` is not being changed in a code block, use `%`, not `!` – Magoo Nov 13 '17 at 18:32
  • Thanks for the tip Magoo, I've changed the second statement to use % and it seems to be working - now I need to combine the two and execute the second code block for the files in the "Numbers" directory – Hayward Nov 13 '17 at 18:37

1 Answers1

0

It appears that from your example result that you also want files with no "#" copied as is to the NoNumber directory. Is that correct?

This script detects the presence of the "#" character in the file name by comparing the filename to one which has had all "#" characters replaced with nothing.

SETLOCAL ENABLEDELAYEDEXPANSION

FOR %%i IN ("*.txt") DO (
    SET "BNAME=%%~ni"
    SET "TNAME=!BNAME:#=!

    IF "!BNAME!" NEQ "!TNAME!" (
        REM A # was found
        REM NB: This assumes that there is a space before the #
        MOVE "%%~i" "NoNumbers\!TNAME:~0,-4!.json"
    ) ELSE (
        COPY /Y "%%~i" "NoNumbers\!BNAME!.json"
        MOVE "%%~i" "Numbers\!BNAME!.json"
    )
)

This script does nothing to detect filename collisions. What happens if both BETA #101.txt and BETA #102.txt exist?

lit
  • 14,456
  • 10
  • 65
  • 119