Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[DOS Batch] File verplaatsen en hernoemen met ophogen

Pagina: 1
Acties:

  • FireAge
  • Registratie: Augustus 2002
  • Laatst online: 19:11
Achtergrond:
Ik speel een oude PBEM game (VGA Planets) die nog onder DOS moet draaien. Dit spel draai ik in een DosBox. Elke drie dagen krijg ik in de email een nieuwe .RST file. Deze file moet worden uitgepakt, en vervolgens kun je je beurt doen om een .TRN te maken, die weer moet worden teruggemaild.

Doel:
Nu wil ik een batch file schrijven die een hoop taken voor mij automatiseerd. Ik wil de volgende stappen uitvoeren:
  1. De RST file uitpakken met het programma c2unpack (filenaam = player6.rst)
  2. De RST file verplaatsen naar een folder RST, maar daarbij elke keer de naam wijzigen en ophogen. Dus de eerste beurt moet hij verplaatst worden naar RST\player6.001, de tweede beurt naar RST\player6.002, etc etc.
  3. DosBox aanroepen met een specifieke configuratie file.
Idee is daarbij, dat punt 1 en 2 alleen gebeuren, als er daadwerkelijk een RST aanwezig is. Als die er niet is, dan moet alleen DosBox worden aangeroepen. Ik heb een deel al voor elkaar, maar worstel met het rename stuk. Dus ik hoop dat er hier meer ervaring batchers zijn :P

Eigen input:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
C:
cd C:\games\VGAPlan\planets
IF EXIST FedWar3\player6.rst goto :unpackTRN
goto :runTRN

:unpackTRN
C:\games\VGAPlan\PCC2\c2unpack -w 6 C:\games\VGAPlan\planets\FedWar3
MOVE C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\TRN\player6.001

:runTRN
"C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe" -conf "C:\games\VGAPlan\Planets\FedWar3\2_dosbox-FedWar3.conf" -noconsole -exit
pause
C:
cd C:\games\VGAPlan
PCC2\c2mkturn planets\FedWar3
pause

Het gaat me dus om de tweede statement bij :unpackTRN

Wie heeft er een goede suggestie hoe ik kan bepalen welke .001, .002 etc file al aanwezig is, en welke naar ik de nieuwe dus moet geven.

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Ik zie zo snel niet hoe je dat in Batch kan doen. Je kan wel een eigen MoveFile-programma maken in een hogere programmeertaal zoals bv C#:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using System.IO;

namespace MoveFile
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
                args = new string[] { @"C:\player.rst", @"C:\test" };

            string src_path = args[0];
            string src_name = Path.GetFileNameWithoutExtension(src_path);

            string dst_dir = args[1];

            int max = 0;
            foreach (string my_path in Directory.EnumerateFiles(dst_dir))
            {
                string my_name = Path.GetFileNameWithoutExtension(my_path);
                string my_ext = Path.GetExtension(my_path);

                if (my_name == src_name && my_ext.StartsWith("."))
                {
                    int my_value = int.Parse(my_ext.Substring(1));
                    max = Math.Max(max, my_value);
                }
            }

            string dst_ext = string.Format("{0:D3}", max + 1);
            string dst_path = dst_dir + '\\' + src_name + '.' + dst_ext;

            Console.WriteLine("Moving file...");
            Console.WriteLine("From: {0}", src_path);
            Console.WriteLine("To: {0}", dst_path);

            File.Move(src_path, dst_path);
        }
    }
}


Na compileren roep je het zo aan:
MoveFile C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\TRN

[ Voor 30% gewijzigd door Daos op 24-08-2013 21:13 . Reden: Code ingekort ]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Persoonlijk zou ik het in een scripttaal als autoit3 bijv doen, maar ik vermoed dat als je binnen een for-loop van 1 tot 999 een if exists doet met die naam en dan een variabele zetten met de eerst nog beschikbare naam dat het technisch wel moet kunnen.

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
@DaoS: Ga alsjeblieft niet lopen rommelen met Substring, IndexOf en whatnot; er zijn fatsoenlijke alternatieven in de BCL voorhanden voor path- en file(name) bewerkingen. Combineer dat met een beetje Danoontje Linq-powerrrr en dan heb je al snel zoiets:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System.IO;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        var dest_path = @"D:\test";
        var src_path = @"C:\player6.rst";

        var lastfile = new DirectoryInfo(dest_path)
                        .GetFiles(Path.GetFileNameWithoutExtension(src_path) + ".*")
                        .Select(f => new
                        {
                            FileName = f.Name,
                            Index = int.Parse(f.Extension.Replace(".", ""))
                        })
                        .OrderByDescending(f => f.Index)
                        .First();

        var newfilename = Path.GetFileNameWithoutExtension(lastfile.FileName)
            + "." + (lastfile.Index + 1).ToString().PadLeft(3, '0');

        File.Move(src_path, Path.Combine(dest_path, newfilename));
    }
}


[edit]
En dan nu stiekem 5 minuten voor ik post je post editten en wél de juiste functies gebruiken, stiekemerd! :P

[edit2]
En met wat uitleg erbij:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System.IO;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        //TODO: Get these values from the commandline arguments. Exercise for reader ;-)
        var dest_path = @"D:\test";
        var src_path = @"C:\player6.rst";

        //Get the last file in the directory
        var lastfile = new DirectoryInfo(dest_path)
                        //Find files that match the src_path's filename without the extension
                        .GetFiles(Path.GetFileNameWithoutExtension(src_path) + ".*")
                        //Create an anonymous object with filename and index
                        .Select(f => new
                        {
                            FileName = f.Name,
                            Index = int.Parse(f.Extension.Replace(".", ""))
                        })
                        //Get only the highest-numbered file
                        .OrderByDescending(f => f.Index)
                        .First();

        //Compose new filename
        var newfilename = Path.GetFileNameWithoutExtension(lastfile.FileName)
            + "." + (lastfile.Index + 1).ToString().PadLeft(3, '0');

        //I like to move it, move it!
        File.Move(src_path, Path.Combine(dest_path, newfilename));
    }
}

[ Voor 39% gewijzigd door RobIII op 24-08-2013 22:04 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Wim-Bart
  • Registratie: Mei 2004
  • Laatst online: 10-01-2021

Wim-Bart

Zie signature voor een baan.

Zo iets als dit :-) Moet wel in Windows XP lopen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@ECHO OFF
REM -----------------------------
REM INITIALIZE
REM -----------------------------
SET DONE=N

REM GO TO Planets folder
CD /D C:\games\VGAPlan\planets

REM Check if rst file exists and if not goto runTRN
IF NOT EXIST FedWar3\player6.rst GOTO runTRN
  REM First unpack with c2unpack
  C:\games\VGAPlan\PCC2\c2unpack -w 6 C:\games\VGAPlan\planets\FedWar3
  REM Second, call MoveRST with numbers 0 through 999
  FOR /L %%n IN (0,1,999) DO CALL :MoveRST %%n

REM -------------------
REM RUNTRN
REM -------------------
:runTRN
  "C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe" -conf "C:\games\VGAPlan\Planets\FedWar3\2_dosbox-FedWar3.conf" -noconsole -exit
  PAUSE
  
  CD /D C:\games\VGAPlan
  PCC2\c2mkturn planets\FedWar3
  PAUSE
  GOTO End


REM ------------------
REM Moce RST Routine, takes a number from 0 to 999 as parameter
REM ------------------
:MoveRST
  REM If DONE is set to Y the routine does not need to do anyting anymore
  IF DONE==Y GOTO :EOF
  REM Create the extension with the parameter, 1 becomes 001, 91 becomes 0091, 234 becomes 00234
  SET FEXT=00%1
  REM Take the last 3 characters from FEXT
  SET FEXT=%FEXT:~-3%
  REM Look if file exists and if so, skip the routine
  IF EXIST C:\games\VGAPlan\planets\Fedwar3\TRN\player6.%FEXT% GOTO :EOF

  REM The file did not exist, so move it
  MOVE C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\TRN\player6.%FEXT%
  REM Set Done to Y so the routine will not run again
  SET DONE=Y
GOTO :EOF

:End

Beheerders, Consultants, Servicedesk medewerkers. We zoeken het allemaal. Stuur mij een PM voor meer info of kijk hier De mooiste ICT'er van Nederland.


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Gomez12 schreef op zaterdag 24 augustus 2013 @ 21:00:
maar ik vermoed dat als je binnen een for-loop van 1 tot 999 een if exists doet met die naam en dan een variabele zetten met de eerst nog beschikbare naam dat het technisch wel moet kunnen.
Kan ook inderdaad:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@echo off
rem usage: script C:\player.rst C:\Test\player

setlocal EnableDelayedExpansion
for /L %%n in (1 1 999) do (
  set "num=00%%n"
  set "num=!num:~-3!"
  set "to=%2.!num!"

  if not exist !to! (
    echo Moving file... 
    echo From: %1
    echo To: !to!

    move %1 !to!
    goto exit
  ) 
)

:exit


Dit roep je zo aan (2e argument is anders dan in mijn eerste post):
call MoveFile C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\TRN\player6

  • FireAge
  • Registratie: Augustus 2002
  • Laatst online: 19:11
Bedankt voor de code opzet, maar ik wil het toch eigenlijk wel in een batch file voor elkaar krijgen. (gewoon omdat het moet kunnen :P )

Misschien als ik nu een current.trn file maak en daar gewoon een getal in schrijf en het er weer met "type" uithaal. Dan hoef ik ook geen enorme for-loops te draaien.

Ik ga even wat proberen. Het is wel windows 7 trouwens :P

EDIT:
Ah zal me leren om een half antwoord te typen, en dan na een half uur verder te gaan :P
Bedankt voor de hulp, nu moet het goedkomen!

@WimBart
Echt geweldig zo met de uitleg erbij. Maakt het erg makkelijk te verwerken.
Waarom heb je de RunTurn voor de move gezet?
Idee is dat na een move je de turn start, dat werkt zo toch niet?(ga het even proberen)

Vergeet die vraag, niet goed gelezen dat werkt natuurlijk wel.

[ Voor 41% gewijzigd door FireAge op 24-08-2013 22:55 ]


  • FireAge
  • Registratie: Augustus 2002
  • Laatst online: 19:11
Hmm, het loopt niet helemaal zoals ik zou denken.

Hij verplaats wel de file naar de juiste folder.
Maar als ik de echo aan is, dan geeft hij een file not found melding voor alle files die niet in de target folder staan.

Dus als ik het aantal op 5 limiteer, en daar dan .000 en .001 in zet, dan geeft hij 3 file not found meldingen. Terwijl ik zou verwachten dat hij ophoudt nadat het gelukt is.

Als ik een pause aanbreng na:

code:
1
  MOVE C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\TRN\player6.%FEXT%

En dan handmatig even weer een rst in de folder zet, dan gaat hij hem weer verplaatsen.
Blijkbaar werkt SET DONE=Y niet.

Ik puzzel even verder.

EDIT:
Moet dat geen IF %DONE%=Y zijn?

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Als je het script van WimBart gebruikt, regel 35 verwijst naar iets maar bestaat dat ook?

  • FireAge
  • Registratie: Augustus 2002
  • Laatst online: 19:11
Net gechecked, als ik er
code:
1
IF %DONE%==Y

Dan werkt het wel prima.

Eerst slapen, morgen het eindresultaat :)

[ Voor 21% gewijzigd door FireAge op 24-08-2013 22:59 ]


  • FireAge
  • Registratie: Augustus 2002
  • Laatst online: 19:11
Eindresultaat.

Ik heb besloten de code van Wim-Bart te pakken, en die om te bouwen. (waarvoor nogmaals dank!)
Ik heb de FOR loop omgebouwd in een WHILE loop zodat hij ophoudt met checken zodra er een move is geweest. Verder moest de DONE variabele opgevraagd worden met %% en heb ik de echo hier en daar nog aan- en uitgezet om de relevante passages aan mij te laten zien. Verder had ik hier en daar TRN en RST door elkaar gehaald, dat heb ik nu ook opgeschoond.

Het werkt perfect zo.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@ECHO OFF
REM -----------------------------
REM INITIALIZE
REM -----------------------------
SET DONE=N
SET NRST=1

REM GO TO Planets folder
CD /D C:\games\VGAPlan\planets

REM Check if rst file exists and if not goto runTRN
IF NOT EXIST FedWar3\player6.rst GOTO runTRN
  REM First unpack with c2unpack
  @ECHO ON
  C:\games\VGAPlan\PCC2\c2unpack -w 6 C:\games\VGAPlan\planets\FedWar3
  @ECHO OFF
  REM Second, call MoveRST with numbers 0 through 999, but stop when the file move has been done.
:while1
  IF %NRST% LSS 1000 (
    IF %DONE%==N (
      CALL :MoveRST %NRST%  
      SET /A "NRST=NRST+1"
      GOTO while1
    )
  )

REM -------------------
REM RUNTRN
REM -------------------
:runTRN
  "C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe" -conf "C:\games\VGAPlan\Planets\FedWar3\2_dosbox-FedWar3.conf" -noconsole -exit 
  CD /D C:\games\VGAPlan
  @ECHO ON
  PCC2\c2mkturn planets\FedWar3
  PAUSE
  @ECHO OFF
  GOTO End


REM ------------------
REM Move RST Routine, takes a number from 0 to 999 as parameter
REM ------------------
:MoveRST
  REM If DONE is set to Y the routine does not need to do anyting anymore
  IF %DONE%==Y GOTO :EOF
  REM Create the extension with the parameter, 1 becomes 001, 91 becomes 0091, 234 becomes 00234
  SET FEXT=00%1
  REM Take the last 3 characters from FEXT
  SET FEXT=%FEXT:~-3%
  REM Look if file exists and if so, skip the routine
  IF EXIST C:\games\VGAPlan\planets\Fedwar3\RST\player6.%FEXT% GOTO :EOF

  REM The file did not exist, so move it
  @ECHO ON
  MOVE C:\games\VGAPlan\planets\FedWar3\player6.rst C:\games\VGAPlan\planets\Fedwar3\RST\player6.%FEXT%
  @ECHO OFF
  REM Set Done to Y so the routine will not run again
  SET DONE=Y
GOTO :EOF

:End
Pagina: 1