2

Short story: I'm trying to write a script that will use FFmpeg to convert the many files stored in one directory to a "standard" mp4 format and save the converted files in another directory. It's been a learning experience (a fun one!) since I haven't done any real coding since using Pascal and FORTRAN on an IBM 370 mainframe was in vogue.

Essentially the script takes the filename, strips the path and extension off it, reassembles the filename with the path and an mp4 extension and calls FFmpeg with some set parameters to do the conversion. If the directory contains only video files with without spaces in the names, then everything works fine. If the filenames contain spaces, then FFmpeg is not able to process the file and moves on to the next one. The error indicates that FFMpeg is only seeing the filename up to the first space. I've included both the script and output below.

Thanks for any help and suggestions you may have. If you think I should be doing this in another way, please by all means, give me your suggestions. As I said, it's been a long time since I did anything like this. I'm enjoying it though.

I've include the code first followed by example output.

for file in ./TBC/*.mp4
    do

    echo "Start of iteration"
    echo "Full text of file name:" $file

    #Remove everything up to  "C/" (filename without path)
    fn_orig=${file#*C/}
    echo "Original file name:" $fn_orig

    #Length of file name
    fn_len=${#fn_orig}
    echo "Filename Length:" $fn_len

    #file name without path or extension
    fn_base=${fn_orig:0:$fn_len-4}
    echo "Base file name:" $fn_base

    #new filename suffix
    newsuffix=".conv.mp4"

    fn_out=./CONV/$fn_base$newsuffix
    echo "Converted file name:" $fn_out

    ffmpeg -i $file -metadata title="$fn_orig" -c:v libx264 -c:a libfdk_aac -b:a 128k $fn_out

    echo "End of iteration"
    echo
    done
echo "Script completed"

With the ffmpeg line commented out, and two files in the ./TBC directory, this is the output that I get

    Start of iteration
    Full text of file name: ./TBC/Test file with spaces.mp4
    Original filename: Test file with spaces.mp4
    Filename Length: 25
    Base filename: Test file with spaces
    Converted file name: ./CONV/Test file with spaces.conv.mp4
    End of iteration

    Start of iteration
    Full text of file name: ./TBC/Test_file_with_NO_spaces.mp4
    Original file name: Test_file_with_NO_spaces.mp4
    Filename Length: 28
    Base file name: Test_file_with_NO_spaces
    Converted file name: ./CONV/Test_file_with_NO_spaces.conv.mp4
    End of iteration

    Script completed

I won't bother to post the results when ffmpeg is uncommented, other than to state that it fails with the error: ./TBC/Test: No such file or directory

The script then continues to the next file which completes successfully because it has no spaces in its name. The actual filename is "Test file with spaces.mp4" so you can see that ffmpeg stops after the word "Test" when it encounters a space.

I hope this has been clear and concise and hopefully someone will be able to point me in the right direction. There is a lot more that I want to do with this script such as parsing subdirectories and ignoring non-video files, etc.

I look forward to any insight you can give!

7
  • when asking a question; make it minimal! this is way too much text and code to get to the actual question! Commented Jan 13, 2016 at 7:21
  • 1
    did you try my answer? Did it work? Any updates? Commented Jan 13, 2016 at 8:00
  • Hi, Sorry...went to bed and just got up. I tried your idea and it still doesn't work...no luck. Any ideas? Commented Jan 13, 2016 at 14:06
  • As I asked; do you still have the exact same error? what is your error? you can use bash -x <yourscript> to debug the exact command that is causing problems. Commented Jan 13, 2016 at 14:07
  • Yes, I still receive the same exact error which is: "./TBC/Test: No such file or directory" since the name of the file it is halting on is "Test file with spaces.mp4", it indicates to me that the argument passed (the filename) is only passed up to the first space. The script continues after to go on and process the second file in the directory successfully. That file's name doesn't contain any spaces. Commented Jan 13, 2016 at 14:10

2 Answers 2

1

try quoting you output file:

ffmpeg -i "$file" ... "$fn_out"

bash separates arguments based on spaces, so you have to tell him that $fn_out is one single argument; whence the "" to show that this is one argument.

Sign up to request clarification or add additional context in comments.

2 Comments

Even with the quotes around the variable, the iteration with the filename with spaces still kicks an error in FFmpeg. THe Quotes don't seem to hold the name together as one unit. Any ideas?
It was indeed the missing quotes in the input field. I guess because it was successfully reading the files with spaces from the directory, but not writing the file to it, I became focused on output when all along it was the input parameter that was causing the trouble. Thanks again for your help!
0

There is another edge-case where spaces break bash for loops.

"BASH for loop works nicely under UNIX / Linux / Windows and OS X while working on set of files. However, if you try to process a for loop on file name with spaces in them you are going to have some problem. For loop uses $IFS variable to determine what the field separators are. By default $IFS is set to the space character..."

https://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html

Before:

for file in $(find . -name '*.txt'); do echo "$file"; done

Outputs:

./files/my
documents/item1.txt
./files/my
documents/item2.txt
./files/my
documents/item3.txt

Therefore you should set IFS to ignore spaces.

After:

IFS=$'\n'
for file in $(find . -name '*.txt'); do echo "$file"; done

Outputs:

./files/my documents/item1.txt
./files/my documents/item2.txt
./files/my documents/item3.txt

Comments

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.