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%
1
  • 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... Commented Nov 3, 2016 at 13:28

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

6 Comments

Still get the same result
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"
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?
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
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
|
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...)

3 Comments

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?
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.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.