Mac Terminal (Bash) batch program to get multimedia file info using ffmpeg - macos

I have a Mac computer. Usually all my batch programming is done on my PC. So I tried to create what I assumed would be a simple equivalent using a Mac shell. Obviously as you all know that was foolish of me to think that. After 2 days of scowering the web I found the closest thing I could to what I was looking for. But no, this doesn't work either.
All I'd like to do is throw a multimedia file onto the script, and have the terminal give me the ffmpeg info output. In my searching I did find this "$#" which as far as I can tell is the windows bat equivalent of %*. Meaning you can throw files on the script and the script refers to those files as variables which can be processed. So I believe what I want to do is possible.
Again the code at the bottom is just to look through the current directory of all .mov files and run ffmpeg. It doesn't work. But.. if no one can help me figure out the actual thing I'd like to do then I'd settle with something like below that does actually work.
#!/bin/bash
FFMPEG=/Applications/ffmpeg
FIND=/usr/bin/find
FILES=$(${FIND} . -type f -iname "*.mov")
if [ "$FILES" == "" ]
then
echo "There are no *.mov file in $(pwd) directory"
exit 1
fi
for f in *.mov
do
$FFMPEG -i "$f"
done
If someone can please help me figure this out I'd really appreciate it. Thank you in advance! Jules
I just found this solution from the "similar questions" sidebar, which is similar to the script above, so again, not completely what I wanted but.. didn't matter, didn't work for me. How to batch convert mp4 files to ogg with ffmpeg using a bash command or Ruby

.command files don't receive dropped files as input.
You might just open a Terminal window, type for f in, drop the files on the window, and type ; do ffmpeg -i "$f"; done.
Or save a script like this as an application in AppleScript Editor:
on open argv
set paths to ""
repeat with f in argv
set paths to paths & quoted form of POSIX path of f & " "
end repeat
tell application "Terminal"
do script "for f in " & paths & "; do ffprobe -i \"$f\"; done"
activate
end tell
end open
ffprobe -i is like ffmpeg -i but it doesn't show an error like At least one output file must be specified.
Edit: you could also use Platypus:
Set the script to something like for f; do ffprobe -i "$f"; done.

This might do it:
for FILE in "${#}"
do
/Applications/ffmpeg -i "$FILE"
done

Related

How to prevent file overwriting in bash script?

I am trying to automate a process which take a file type NIFTI, preprocess it, and places the new processed file in an output folder.
deepbrain-extractor -i <input-dir> -o <output-dir>
I wrote this bash script to automate this process for all files in a directory:
for file in path/*.nii
do
deepbrain-extractor -i $file -o path/newfiles
done
The problem is every time the code runs, it overwrites the old files (since all automatically get the same name). Is there a way to prevent that?
Thanks for the suggestions and comments!
seems like using this code gives me what I want.
deepbrain-extractor -i "$file" -o "${file%.nii}.out"
Thanks a lot!!
A common way to get a unique file name is to use the current date and time.
You can combine this with the input file name to ensure that output files are never overwritten.
if [ ! -f "$FILE" ]; then
echo "$FILE does not exist."
for file in path/*.nii
do
deepbrain-extractor -i $file -o path/newfiles_${file##*/}_$(date +"%Y-%m-%d_%H-%M-%S")
done
fi
so the output directory has a name like newfiles_input_2020-11-13_12-34-56
Also see How to create one output file for each file passed to a loop in bash?

Check video files for integrity

I have a library of video files. They get moved around, zipped, unzipped and stuff.
It happened, that some of the files get e.g., transferred/ extracted only partially. This problem usually shows up only when actually watching that video (i.e., the video stops prematurely, which is then really annoying).
Is there a way to batch-verify the integrity of a video library?
I came up with the following, inspired by this question:
find . -regex ".*\.\(avi\|mkv\)" -exec ffmpeg -v error -i {} -f null - \;
The problem here is, that ffmpeg does not include the file name when printing the error messages which means I do not know which file in the batch is erroneous.
To make a long story short:
Is there a way to include the file name in the ffmpeg error messages?
Simply capture the output of ffmpeg and print it out with a proper header if not empty:
find . -regex ".*\.\(avi\|mkv\)" | while read f; do
ffmpeg_out=$(ffmpeg -hide_banner -nostdin -v error -i "$f" -f null - 2>&1)
[[ $ffmpeg_out ]] && echo -e "==> ERROR in $f\n${ffmpeg_out}"
done
I've added a couple of ffmpeg options to ensure proper operations:
-hide_banner turns off the normal FFmpeg preamble, which is just unnecessary noise
-nostdin tells FFmpeg to ignore any (accidental) keyboard interaction

Parse filenames into touch command on OS X

I have a large number of photos on my machine where I'd like to parse the standard naming convention I have created for each file, and then pipe it to the touch command.
For example, I have these files:
2016-08-06-00h28m34.jpg
2016-08-06-00h28m35.jpg
2016-08-06-00h28m36.jpg
I would like to generate (and then run) the following commands:
touch -t 201608060028.34 2016-08-06-00h28m34.jpg
touch -t 201608060028.35 2016-08-06-00h28m35.jpg
touch -t 201608060028.36 2016-08-06-00h28m36.jpg
I can do this manually in a text editor, but it's extremely time-consuming, due to the number of files in each directory. I could also do it in C# and run it over my LAN, but that seems like overkill. Heck, I can even do this in SQL Server, but ... it's OS X and I'm sure there's a simple command-line thing I'm missing.
I've looked at Windows version of Unix touch command to modify a file's modification date from filename part, and Split Filename Up to Define Variables, but I can't seem to figure out how to add in the period for the seconds portion of the script, plus I don't want to add the batch script to each of the hundreds of folders I have.
Any assistance will be greatly appreciated.
Simple Option
I presume you are trying to set the filesystem time to match the EXIF capture time of thousands of photos. There is a tool for that, which runs on OSX, Linux (and Windows if you must). It is called jhead and I installed it on OSX using homebrew with:
brew install jhead
There may be other ways to install it - jhead website.
Please make a back up before trying this, or try it out on a small subset of your files, as I may have misunderstood your needs!
Basically the command to set the filesystem timestamp to match the EXIF timestamp on a single file is:
jhead -ft SomeFile.jpg
So, if you wanted to set the timestamps for all files in $HOME/photos/tmp and all subdirectories, you would do:
find $HOME/photos/tmp -iname \*.jpg -exec jhead -ft {} \;
Option not requiring any extra software
Failing that, you could do it with Perl which is installed on OSX by default anyway:
find . -name \*.jpg | perl -lne 'my $a=$_; s/.*(\d{4})-(\d+)-(\d+)-(\d+)h(\d+)m(\d+).*/$1$2$3$4$5.$6/ && print "touch -t $_\ \"$a\"" '
which gives this sort of output on my machine:
touch -t 201608060028.34 "./2016-08-06-00h28m34.jpg"
touch -t 201608060028.35 "./2016-08-06-00h28m35.jpg"
touch -t 201501060028.35 "./tmp/2015-01-06-00h28m35.jpg"
and if that looks good on your machine, you could send those commands into bash to be executed like this:
find . -name \*.jpg | perl -lne 'my $a=$_;s/.*(\d{4})-(\d+)-(\d+)-(\d+)h(\d+)m(\d+).*/$1$2$3$4$5.$6/ && print "touch -t $_\ \"$a\"" ' | bash -x
And, for the Perl purists out there, yes, I know Perl could do the touch itself and save invoking a whole touch process per file, but that would require modules and explanation and a heap of other extraneous stuff that is not really necessary for a one-off, or occasional operation.

Shell: use of for on a variable list

Unfortunately my shell skills are very bad and I would need some help in running a simple script on my QNAP to fix some date problem on some videos.
The script I put in place is very easy:
in a given folder
check if there are .mp4 files starting with VID_
if so, for each of them run a given exiftool command
Here is the script so far, but I guess I am not using the right way to call the variable:
#!/bin/sh
# set target directories
dir="/share/Multimedia/Pictures/"
# move to target directory
cd "$dir"
# check if there is some .mp4 file starting with "VID_" in the folder
VID=$(ls -A $dir | grep 'VID_' | grep './mp4')
if
["$VID"];
then
# for each file in the list
for f in $VID
do
# change all date metadata according to its filename
exiftool "-*date<filename" -wm w $f
done
else
fi
Thanks for your help!
ps: the exiftool instruction is correct (except probably for the variable)
There isn't a need to script this, doing so just slows you down as you have to call ExifTool for every file. ExifTool can do all the files in one pass:
ExifTool -ext mp4 '-*date<filename' -wm w /path/to/dir/VID_*
The -ext mp4 options limits the command to only mp4 files. Since you seem to be on a linux/mac system, the double quotes had to be changed to single quotes. Double quotes are needed on Windows systems, single quotes on linux/mac systems.
Your code is probably failing due to use of:
grep './mp4'
Since there is no / before mp4.
Better to have your script as:
#!/bin/sh
# set target directories
dir="/share/Multimedia/Pictures/"
# move to target directory
cd "$dir"
for f in VID_*.mp4; do
exiftool "-*date<filename" -wm w "$f"
done
No need to parse output of ls here and there is no need to use grep since glob VID_*.mp4 will do the job of finding correct files.

pdf2swf using MAC OS Batch command or Apple script

How do I write a batch process on the Mac for pdf2swf, I want to convert all pdfs in a folder into swf. But pdf2swf doesn't have a option to convert a folder of pdfs to swfs, you have to do it one at a time. I'm not sure how if I should use a Apple script or a Shell script, either one I'm not sure how to get or assign a file name variable.
pdf2swf file_name_variable.pdf -o file_name_variable.swf -T 9 -f
Thanks
Open up Terminal and do something like this:
$ for f in `find /path/to/my/pdf/directory -name \*.pdf` ; do
> echo "Processing $f..."
> pdf2swf $f -o ${f/.pdf/.swf} -T 9 -f
> done

Resources