0

I compress a video with FFMPEG by means of a batch scripting one-liner with a FOR LOOP. After compressing I want to remove the original file.

This code perfectly makes the compressing job, but the original file is not being removed:

for %%i in (*.mp4) do ffmpeg -i "%%i" -vcodec libx265 -crf 28 "%%~ni"-small.mp4&&del "%%i"
pause

What have I missed?

By the way, this is a near to perfect compression ratio for any kinds of educational videos, tutorials, etc. which have occupied your hard drive.

4
  • 1
    Try the DO clause like this: DO (ffmpeg -i "%%i" -vcodec libx265 -crf 28 "%%~ni-small.mp4" && del "%%i") Commented Sep 30, 2020 at 15:04
  • 1
    There are many ways to do this in addition to the way that @Squashman points out. You can use "enabledelayedexpansion" to allow you to write lines without worrying if they succeded. I myself prefer "batch functions". My point? There are many ways to do things and you might want to use a different method if you need more than a one liner. Commented Sep 30, 2020 at 15:25
  • 1
    You should improve your way of quotation, change "%%~ni"-small.mp4 to "%%~ni-small.mp4" Commented Sep 30, 2020 at 16:49
  • 1
    @Squashman, the parentheses should not make any difference; perhaps ffmpeg sets its exit code to a non-zero value, hence && does not execute the following del command; for testing I would temporarily use & instead of && Commented Sep 30, 2020 at 17:02

2 Answers 2

1

I would assume that this methodology will serve you better:

@For /F "EOL=? Delims=" %%G In ('Dir /B /A:-D "*.mp4" ^| ^
 "%__AppDir__%findstr.exe" /IR "\.mp4$" ^| ^
 "%__AppDir__%findstr.exe" /IRV "\-small\.mp4$"'
) Do @If Not Exist "%%~nG-small%%~xG" (
    ffmpeg.exe -i "%%G" -vcodec libx265 -crf 28 "%%~nG-small%%~xG"
    If Not ErrorLevel 1 If Exist "%%~nG-small%%~xG" Del /A /F "%%G")

The idea is to get a directory listing of all files with an .mp4 extension. Using the first findstr to exclude any files which match the short, (8.3), names. It then pipes those through another findstr search, to exclude any of those files which already have -small appended to their basename. Next it checks to make sure that there are no existing files within that directory, with the same basename plus the -small basename suffix, (preventing possible overwrites). If all of those pass, ffmpeg.exe should be invoked, (subject to ffmpeg.exe being in the current directory, within %PATH%, or registered as executable with its location in the registry). Once the conversion has completed, the script checks the returned ErrorLevel was less than 1, (to ensure it was successful), and if so, whether the new file, (with the -small basename suffix) exists. If so it will proceed with the deletion, using the Del command.

If you wanted to try it again using conditional operators instead of the ErrorLevel, then it would look like this:

@For /F "EOL=? Delims=" %%G In ('Dir /B /A:-D "*.mp4" ^| ^
 "%__AppDir__%findstr.exe" /IR "\.mp4$" ^| ^
 "%__AppDir__%findstr.exe" /IRV "\-small\.mp4$"'
) Do @If Not Exist "%%~nG-small%%~xG" (
    ffmpeg.exe -i "%%G" -vcodec libx265 -crf 28 "%%~nG-small%%~xG" && (
        If Exist "%%~nG-small%%~xG" Del /A /F "%%G"))
Sign up to request clarification or add additional context in comments.

Comments

0

I just put the '/f' after DEL and it perfectly does the job. I don't know if there are any shortcomings of the forced deletion but it works.

A final line:

for %%i in (*.mp4) do ffmpeg -i "%%i" -vcodec libx265 -crf 28 "%%~ni"-small.mp4&&del /f "%%i"
pause

3 Comments

Whilst it's good to see that you've solved it, I used the /F option with my Del command in my provided answer sixteen hours ago! In addition to that I improved your script, and explained to you the methodology it used. Is there a particular reason why you have not accepted it as your preferred solution?
@Compo I am grateful for your tribute and it's definitely better than my solution. But I wanted just a one-liner which gets the job done with understanding why I can't do without "/F". I indeed didn't pay much attention to your using "/F" because the whlole code is too much difficult for me to understand. I marked your answer as a solution.
One line code, does not run any quicker, is harder to read, and in your case, is not robust enough for a real world scenario. I haven't, in my code added anything which should not be there, and the second example is a one liner too. I've simply split the long lines for readability.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.