I am trying to run a bash script but am encountering some errors.
I want to recursively make the command search through the folder and look for all mp4 files. Then i want it to run the ffprobe command and output it to a csv file in a different location with the filename of the mp4 it ran with .csv
So far i have this
#!/bin/bash
for file in /this/is/directory1/*.mp4; do
ffprobe -show_packets -of csv=print_section=0 $file >> /this/is/directory2/${file}.csv
done
Try this:
find . -type f -name "*.mp4" | xargs -I{} bash -c "ffprobe -show_packets -of csv=print_section=0 {} > /tmp/\$(basename {} | cut -d. -f1).csv"
OR without using xargs
find . -type f -name "*.mp4" -exec bash -c "ffprobe -show_packets -of csv=print_section=0 {} > /tmp/\$(basename {} | cut -d. -f1).csv" ';'
Change the path of directory output file in the command above.
Related
I am trying to rename the output files that are coming out of ffmpeg processes that I have spawned using find and xargs. I have a directory of files that I would like to convert to a certain format and all those files should ultimately be named .mov. So I am filtering out .mp4 & .mov files and then using xargs to pass it on to ffmpeg.
Suppose there are files such as abc.mp4, abcd.mp4, abcde.mp3, bcd.mov etc in the current working dir and then I am doing something like this to filter out just the mp4 and mov files and pass it on to ffmpeg for encoding:
find . -type f -name "*.mp4" -o -name "*.mov" | xargs -n 1 -p 5 -I '{}' ffmpeg -i '{}' ....... $PWD/{}"_h264.mov"
This will do what I want ffmpeg to do but it will name the files like
abc.mp4_h264.mov,abcd.mp4_h264.mov,bcd.mov_h264.mov
What I would ideally like to achieve is to name the output files as
abc_h264.mov,abcd_h264.mov,bcd_h264.mov
I am not getting any sparks in my brain on how to do that at the place where I specify the output files of ffmpeg. I know that I can call basename command using xargs like this
find . -type f -name "*.mp4" -o -name "*.mov" | xargs -n 1 basename | rev | cut -d . -f 2 | rev
and extract the filename without the extension but if i use that then how can I pass it on to ffmpeg as the input file because it would have lost the extension when it comes out of xargs and ffmpeg will throw an error.
Could anyone help me achieve this in one go where I can specify what 'basename' is doing but where I am specifying the output file name of ffmpeg please?
Thanks very much for any help that you can provide. Really appreciate the community.
Would you please try the following:
find . -type f -name "*.mp4" -o -name "*.mov" | xargs -I {} -n 1 -P 5 bash -c 'org="{}"; new="$PWD/${org%.*}_h264.mov"; ffmpeg -i "$org" {options} "$new"'
But it is not efficient for spawning bash command as a subprocess
multiple times. If you do not have a specific reason to use find
and xargs, it will be simpler to say:
for org in *.mp4 *.mov; do
new="$PWD/${org%.*}_h264.mov"
ffmpeg -i "$org" {options} "$new"
done
Not sure if this is possible...
I'm trying to write a terminal command (linux) that would find all video files with a specific extension and then convert them using HandBrakeCLI
I have the first half of that down:
find . -type f -name "*.avi*" -exec
And I have a working HandBrakeCLI command:
HandBrakeCLI -i file.mkv -o file2.mkv -e x265 --vfr -q 20 --all-audio --all-subtitles
What I have been unable to figure out is how to insert the file name/path for the files found in the find into the file.mkv and then output the converted file with the same file name but in an mkv format.
Is it possible to do this in one line or do I need to break this out in a bash script?
As a one-liner, try something like:
find . -type f -name "*.avi" -print0 | perl -pe 's/\.avi\0/\0/g' | xargs -0 -I% HandBrakeCLI -i %.avi -o %.mkv -e x265 --vfr -q 20 --all-audio --all-subtitles
-print0 option in find prints the filename on the standard output, followed by a null character.
The following perl snippet removes the .avi extention to supply the basename to xargs.
-I% option in xargs replaces "%" with names read from standard input.
I use
find . -name "*.mp4" -print0 | xargs -0 -I $ bash -c "ffmpeg -v error -xerror -i $ -f null - || echo $"
to go over a directory and print bad video files (as ffmpeg sees it)
if I run it in a directory with only mp4 files, it will print the name of file - but, if I run it on the parent folder (a folder with many folders, each has mp4 files) I only get $ being echoed
What am I doing wrong?
With GNU Parallel it looks like this:
find . -name "*.mp4" -print0 |
parallel -0 "ffmpeg -v error -xerror -i {} -f null - || echo {}"
It is tested with filename containing ', " and space.
ls -1 | xargs --verbose -I{} basename {} \
| sed 's/\.[^.]*$//' \
| xargs -I{} lame {}.* {}.wav
Using this code to convert all the wav files in the folder to mp3 throws a error:
xargs : lame : No such file or directory
Try this:
find . -type f -name "*.wav" -exec bash -c 'mv $0 ${0/\.wav/\.mp3}' {} \;
find - will recursively find for a file type starting current directoy with name like *.wav
-exec will move file with .wav extension to .mp3.
why not a loop instead of multiple xargs ?
LameApp="/YourAppPath/lame.exe"
ls | while read WavFileWExt
do
"${LameApp}" "${WavFileWExt%.*}.mp3" "${WavFileWExt}"
done
I'm looking for a way to automate renaming all images with a wrong filename extension. So far I at least found out how to get the list of all these files:
find /media/folder/ -name *.jpg -exec file {} \; | grep 'PNG\|GIF' > foobar.txt
find /media/folder/ -name *.png -exec file {} \; | grep 'JPEG\|GIF' >> foobar.txt
find /media/folder/ -name *.gif -exec file {} \; | grep 'JPEG\|PNG' >> foobar.txt
However, I would also like to automate the renaming. I tried things like
find /media/folder/ -name *.jpg -exec file {} \; | grep -l PNG | rename s/.jpg/.png/
but in this case grep -l or grep -lH don't list only filenames like I thought they would.
The -l and -H flags of grep are not useful in your example. These flags have no effect when used with the standard input, like in your example coming from the pipe. These flags only work if you specify files (or directories and the -r flag for recursion), for example:
grep -rl PNG path/to/dir1 file2 file3
In your example the -l has no effect, so the output is the complete lines that matched PNG, which in your example probably look something like this:
icon.png: PNG image, 512 x 512, 8-bit/color RGBA, non-interlaced
To get only the filename, maybe you can cut off everything after the colon like this:
find /media/folder/ -name *.jpg -exec file {} \; | grep PNG | sed -e s/:.*// | rename s/.jpg/.png/