Search code examples
windowspowershellbatch-filecmd

Script .bat to move files


I'm writing a batch script with cmd.exe and powerShell.exe commands, to copy a .txt file, (which is created by a third-party software), in its installation folder, to another place.

The main problem is that when I run the .bat file and it copies the file, the resulting copy hasn't the same content, it adulters the original content.

Here follows the code:

@echo off
set "origin_folder=C:\Program Files (x86)\PaperCut Print Logger\logs\"
set "destiny_folder=L:"

rem takes the most recent file
for /f "delims=" %%I in ('powershell -Command "& {Get-ChildItem '%origin_folder%' | Sort-Object LastWriteTime -Descending | Select-Object -First 1}"') do (
    set "recent_file=%%I"
)

if not defined recent_file (
    echo No file found
    exit /b 1
)

rem Gets computer name
for /f "delims=" %%a in ('hostname') do set "computer_name=%%a"

rem Gets date
for /f "tokens=1-2 delims=/" %%a in ('echo %date%') do (
    set "month=%%b"
    set "day=%%a"
)

rem Assembly file's name
set "new_name=%computer_name%_%day%-%month%.txt"

rem Moves the most recent file to the destiny folder
move "%recent_file%" "%destiny_folder%"

echo Successfully moved: %recent_file% -> %destiny_folder%\%new_name%

The content was expected to be a number, but I get ...

Successfully moved: %recent_file% -> %destiny_folder%

... in its content (%% filled). I tried exclude this line, but the code does nothing instead.


Solution

  • @ECHO OFF
    SETLOCAL
    set "origin_folder=C:\Program Files (x86)\PaperCut Print Logger\logs\"
    set "destiny_folder=L:"
    set "origin_folder=U:\Program Files (x86)\PaperCut Print Logger\logs"
    set "destiny_folder=U:"
    
    rem takes the most recent file
    rem for /f "delims=" %%I in ('powershell -Command "& {Get-ChildItem '%origin_folder%' | Sort-Object LastWriteTime -Descending | Select-Object -First 1}"') do (
    for /f "tokens=5" %%I in ('powershell -Command "& {Get-ChildItem '%origin_folder%' | Sort-Object LastWriteTime -Descending | Select-Object -First 1}"') do (
        set "recent_file=%%I"
    )
    
    if not defined recent_file (
        echo No file found
        exit /b 1
    )
    
    rem Gets computer name
    for /f "delims=" %%a in ('hostname') do set "computer_name=%%a"
    
    rem Gets date
    for /f "tokens=1-2 delims=/" %%a in ('echo %date%') do (
        set "month=%%b"
        set "day=%%a"
    )
    
    rem Assembly file's name
    set "new_name=%computer_name%_%day%-%month%.txt"
    
    rem Moves the most recent file to the destiny folder
    ECHO move "%origin_folder%\%recent_file%" "%destiny_folder%\%new_name%"
    move "%origin_folder%\%recent_file%" "%destiny_folder%\%new_name%"
    
    echo Successfully moved: %recent_file% -^> %destiny_folder%\%new_name%
    GOTO :EOF
    

    Issues:

    The setlocal line is missing. Including it will mean that when the batch ends, any variations made to the environment will be discarded. This means executing several batch programs within the same session does not accumulate changes.

    [style] IMHO, it is easier to not include trailing \ in values assigned to variables but to add them as required.

    I changed the values assigned to suit my system.

    The value assigned to %%I and hence recent_file was -a---- 07/02/2024 22:35 205826 later.txt for me (file detected was later.txt in my setup) - and appeared to be unterminated.

    Therefore, I changed delims= to tokens=5 to use the fifth token (attribute date time size filename) with the default delimiters. Note that if the filename includes spaces, etc. this will need to be adjusted.

    I echoed a reconstructed move command.

    The move command needed the origin_folder to be included, else the command would attempt to move the file from the current directory.

    Similarly, the destination seemed illogical, so I altered the destination specification to what appears to be more logical.

    and finally, > is a special character meaning redirect stdout (usually console output) and requires to be "escaped" by a caret (^) to disable its special meaning.