0

I am passing command line arguments to a batch script and setting that to a variable like so:

SET dirWhereKept=%1

My problem is, I call a function inside the batch script with 3 arguments. When trying to get those 3 arguments, it gets the ones passed in via the command line instead:

FOR /f "delims=" %%i IN ('DIR /B') DO (
    IF EXIST "%%~i\" (
        rem nothing
    ) ELSE (
        CALL :checkIfWantedFile %%i "%%~xi" %%~zi
    )
)

:checkIfWantedFile
SET file=%~1
SET fileExtension=%~2
SET fileSizeInBytes=%~3

ECHO FILE: %file%
ECHO EXTENSION: %fileExtension%
ECHO SIZE: %fileSizeInBytes%

For example, if I pass in "Avatar ECE (2009)" as the command line argument (which is a directory) and then when calling the function I pass:

  • %%i: Avatar.mp4
  • "%%~xi": ".mp4"
  • %%~zi: some_int

When I do the ECHO's in checkIfWantedFile, the output will be:

FILE: Avatar ECE (2009)
EXTENSION:
SIZE:

As it's getting the command line arguments and not the function ones.

I've had a look at this and some others but cannot get it to work.

EDIT:

The intent of this batch script is to go into a given directory (supplied by the command line arguments) and extract and video file (.mp4, .mkv, .avi) that maybe be in there. Sometimes, the video files are nested in a sub-directory which is why I am checking if the item in the FOR loop is a folder or not. If it is, then the batch script was intended to go into the sub-directory and check whether there are any wanted video files in there or not and extract them.

I added the option that if the script comes across an unwanted file, it is deleted. This is not a requirement though.

The intent is also is that when the directory (supplied in the command line arguments) is cleared of all video files recursively, it is deleted.

Due to unwanted video sample files sometimes being present, I have put in a check as well to check the size of the file in MB, if it is GTR then the %minimumSize% then it is a wanted file and can be extracted

My full code is below:

@ECHO off

SET "dirWhereKept=%1"
SET mp4=".mp4"
SET mkv=".mkv"
SET avi=".avi"
SET needCompressingDir="E:\Need_compressing"
SET minimumSize=200

CD %needCompressingDir%
CD %dirWhereKept%
FOR /f "delims=" %%i IN ('DIR /B') DO (
    IF EXIST "%%~i\" (
        rem do nothing
    ) ELSE (
        GOTO :EOF
        CALL :checkIfWantedFile "%%i" "%%~xi" "%%~zi"
    )
)

:checkIfWantedFile
SET file=%~1
SET fileExtension=%~2
SET fileSizeInBytes=%~3

IF "%fileExtension%" == %mp4% (
    CALL :checkFileSize %fileSizeInBytes%
) ELSE (
    IF "%fileExtension%" == %mkv% (
        CALL :checkFileSize %fileSizeInBytes%
    ) ELSE (
        IF "%fileExtension%" == %avi% (
            CALL :checkFileSize %fileSizeInBytes%
        ) ELSE (
            rem this is not required!
            CALL :deleteFile
        )
    )
)

:checkFileSize
SET /a fileSizeInMB=%~1/1024/1024

IF %fileSizeInMB% GTR %minimumSize% (
    CALL :moveFileToCompress
)

:deleteFile
ECHO "Delete called!"

:moveFileToCompress
MOVE %file% %needCompressingDir%
Community
  • 1
  • 1
wmash
  • 4,032
  • 3
  • 31
  • 69
  • Always use quotes properly: change `SET dirWhereKept=%1` to `SET "dirWhereKept=%~1"`, so the quotes do not become part of the variable value, but prevent the line from failing upon special characters; then change `%%i` to `"%%~i"`, etc.; the `~` removes potential quotes; together with the explicit `""`, this ensures that there is always one pair of `""` around the values... – aschipfl Nov 03 '16 at 13:28

2 Answers2

0

Change %%i in the CALL statement to "%%i"

example:

@ECHO OFF
SET "dirWhereKept=%~1"
IF /I NOT "%CD%"=="%~1" PUSHD "%~1"2>Nul||Exit/B
FOR %%i IN (*.*) DO CALL :checkIfWantedFile "%%i" "%%~xi" "%%~zi"
TIMEOUT -1
EXIT/B

:checkIfWantedFile
ECHO FILE: %~1
ECHO EXTENSION: %~2
ECHO SIZE: %~3
Compo
  • 36,585
  • 5
  • 27
  • 39
  • Still get the same result – wmash Nov 03 '16 at 10:34
  • You cannot possibly get the same result! on your example you are passing five parameters "%~1=Avatar, %~2=ECE, %~3=(2009), %~4=.mp4, %~5=some_int", mine is passing "%~1=Avatar ECE (2009), %~2=.mp4, %~3=some_int" – Compo Nov 03 '16 at 11:02
  • I have figured out an error. On checking whether the current item is a folder or not, if the item is **not** a folder then it does not go into the `else` condition so the function is never called. But if the function is never called, why is it invoked? – wmash Nov 03 '16 at 11:09
  • take a look at the example I have provided, it doesn't see 'folders' so there is no need for the condition. Your function is called because there is nothing to tell your code to stop before the checkIfWantedFile label – Compo Nov 03 '16 at 11:11
  • I need the check though to see if the item is a folder. If it is, I need to check whether files within it are of interest. So, basically, recursively going through sub-directories – wmash Nov 03 '16 at 11:16
  • I have updated the example again now that I have noted your input parameter. I have not performed a recursive check however, merely a check within the directory level provided. You could however do that with `FOR /R %%i IN (*.*)…` – Compo Nov 03 '16 at 11:29
0

Your problem is simply that batch has no concept of a section or procedure. It simply executes the next statement until it reaches end-of-file or exit.

Consequently, the call executes the routine :checkIfWantedFile and when it reaches end-of-file, it returns to the next logical statement after the call - which is the routine :checkIfWantedFile, so it continues executing, using the parameters supplied to the batch itself as %n.

You need to insert a goto :eof line before the :checkIfWantedFile label so that the routine is skipped after it has been executed by the call. Note that the colon in :eof is critical. :eof is defined as end-of-file by cmd.


You are calling a number of subroutines. You need to specifically goto :eof at the end of each and every subroutine, otherwise batch simply continues executing line-by-line. For instance

:deleteFile
ECHO "Delete called!"

:moveFileToCompress
MOVE %file% %needCompressingDir%

If you call :deletefile then the echo is executed, and the move is attempted.

If you call :moveFileToCompress then just the move is attempted.

If you change this to

:deleteFile
ECHO "Delete called!"

GOTO :EOF

:moveFileToCompress
MOVE %file% %needCompressingDir%

goto :eof

then
If you call :deletefile then the echo is executed.

If you call :moveFileToCompress then the move is attempted.

Certainly, a goto :eof at the end-of-file is redundant. I habitually use it so I don't need to remember to insert it before a new added-routine to prevent flow-through.

You would need to follow a similar pattern for each of the subroutines you call.

When I say "report" what I mean is that the batch echoes something to the console, so in your code

:checkIfWantedFile
SET file=%~1
SET fileExtension=%~2
SET fileSizeInBytes=%~3

ECHO FILE: %file%
ECHO EXTENSION: %fileExtension%
ECHO SIZE: %fileSizeInBytes%

This would set the variables and then report their values.

(btw - you may like to use

set file

for reporting these values, which will show the value and name of each existing variable that starts file - a lot less typing...)

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Putting the `GOTO :EOF` completely terminates the batch script. Is there anyway to instead make it go to the next item in the `FOR` loop? – wmash Nov 03 '16 at 16:42
  • It will run through all of the items (filenames and directorynames) in the directory, do nothing if the name found exists as `.\namefound` and report after setting the variables, then continue to the next. When it has reached the end, it will terminate (if the `goto :eof`) is in place with the variables set to the last matching reported name. Perhaps if you were to explain clearly what your intention is, we could suggest an appropriate method. As it is, all we have is your code - we can analyse *that*, but we need a crystal ball to scry your reason for executing the code. – Magoo Nov 03 '16 at 16:57
  • Thank you! I am confused on what you mean by setting the variables and reporting back though? I will edit my question so you can get a clear understanding of what I am trying to do. – wmash Nov 04 '16 at 09:36