How to use original names when using find -exec?

There are .mp4 files that I want to convert.

 $ find . -name '*.mp4' ./01.mp4 ./02.mp4 ./03.mp4 

I was expecting to issue copy-01.mp4 , copy-02.mp4 and copy-03.mp4 with this command.

 find . -name '*.mp4' -exec ffmpeg -i {} -c copy -aspect 16:9 copy-{} ";" 

But this failed with errors Unable to find a suitable output format for 'copy-' . I thought {} represents the file name, right?

How to use original file names when using the -exec find option?

find version:

 $ find --version find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Eric B. Decker, James Youngman, and Kevin Dalley. Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b Features enabled: O_NOFOLLOW(disabled) LEAF_OPTIMISATION FTS() CBO(level=0) 

This is the xargs version.

 xargs --version xargs (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Eric B. Decker, James Youngman, and Kevin Dalley. Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b 

Ffmpeg result

 $ find * -type f -name '*.mp4' -exec ffmpeg -i {} -c copy -aspect 16:9 copy-{} ";" # almost same outputs several times here. ffmpeg version N-50911-g9efcfbe Copyright (c) 2000-2013 the FFmpeg developers built on Mar 13 2013 21:26:48 with gcc 4.7.2 (GCC) configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libgsm --enable-libilbc --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib libavutil 52. 19.100 / 52. 19.100 libavcodec 55. 0.100 / 55. 0.100 libavformat 55. 0.100 / 55. 0.100 libavdevice 54. 4.100 / 54. 4.100 libavfilter 3. 45.103 / 3. 45.103 libswscale 2. 2.100 / 2. 2.100 libswresample 0. 17.102 / 0. 17.102 libpostproc 52. 2.100 / 52. 2.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '24.mp4': Metadata: major_brand : mp42 minor_version : 0 compatible_brands: mp42isomavc1 creation_time : 2012-11-01 13:42:12 encoder : HandBrake 0.9.8 2012071700 Duration: 00:24:58.62, start: 0.000000, bitrate: 474 kb/s Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 640x256, 341 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 180k tbc Metadata: creation_time : 2012-11-01 13:42:12 Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s Metadata: creation_time : 2012-11-01 13:42:12 
+5
source share
3 answers

The correct way is to make a bash script. The problem is the current directory prefix ./

If you really have to do this:

 find * -type f -name '*.mp4' -exec ffmpeg -i {} -c copy -aspect 16:9 copy-{} ";" 

Or if you have xargs :

 find . -name '*.mp4' | xargs -L1 basename | xargs -L1 -I{} ffmpeg -i {} -c copy -aspect 16:9 copy-{} 
+3
source

To access files using ffmpeg, even if they represent several directory levels behind the current directory, you need to pass the entire source path as the -i argument, but basename only as a block for creating the target file name.

If you want them to be copied to the current directory (flattened),

 find . -type f -name '*.mp4' -exec ffmpeg -i {} -c copy -aspect 16:9 copy-"`basename {}`" ";" 

If they should be placed in the same directories as the sources:

 find . -type f -name '*.mp4' -exec ffmpeg -i {} -c copy -aspect 16:9 "`dirname {}`"/copy-"`basename {}`" ";" 
+1
source

This is not a single layer job. Try the script:

 #!/bin/bash while IFS= read -r -d '' FILE do BASE=$(basename "$FILE") COPYFILE=${FILE/$BASE/copy-$BASE} ffmpeg -i "$FILE" -c copy -aspect 16:9 "$COPYFILE" done < <(find . -name '*.mp4' -print0) 

(Of course, with multiple semicolons you can also put this on one line if you want!)

+1
source

Source: https://habr.com/ru/post/1234646/


All Articles