Как я могу использовать два параметра одновременно с xargs?


18

Мне нужно конвертировать видео, но я не знаю, где они, поэтому они мне нужны find. Как я могу дать результат и имя выходного файла для FFmpeg с xargs?

Я уже выяснил, что с помощью этой команды я могу построить два параметра:

find . -iname "*.mov" -printf "%p %f\n"

Я не могу найти ничего связанного в xargsруководстве. Я хочу что-то вроде этого:

find . -iname "*.mov" -printf "%p %f\n" | xargs ffmpeg -i {param1} -f flv {param2}

Как я могу это сделать?


Те из вас наткнуться на этот вопрос , потому что вы ищете ответ на вопрос о многочисленных спорах с xargs вообще возможно , захотите проверить stackoverflow.com/questions/3770432/... .
Крис Олдвуд

Ответы:


4

Нечто подобное будет делать трюк и сохранить полный путь, ручки пространство, переименование folder/movie.movдо folder/movie.flvи т.д.

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "${movie%.mov}.flv"
done

И если я вас неправильно понял, и вы хотите все фильмы .flv в текущем каталоге, используйте вместо этого:

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "$(basename "${movie%.mov}.flv")"
done

3
Если вы хотите, чтобы это был простой способ, просто поместите все в одну строку. ;)
Маттиас Анберг

9

Причина, по которой люди используют xargsв сочетании с find, заключается в том, что несколько имен файлов будут переданы в один и тот же вызов программы независимо от того, какая программа xargsзапускается. Например, если findвозвращает файлы foo , bar и baz , следующее будет выполнено mvтолько один раз:

find sourceDir [...] -print0 | xargs -0 mv -t destDir

По сути, это вызывает mvследующее:

mv -t destDir foo bar baz

Если вам не нужно или не нужно такое поведение (как я полагаю, здесь имеет место), вы можете просто использовать finds -exec.


В этом случае простым решением было бы написать короткий сценарий оболочки, например:

#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
F="$( basename $P )"
ffmpeg -i "$P" -f flv "$F"

Сохранить как myffmpeg.shи запустить chmod +x myffmpeg.sh. Затем выполните следующее:

find . -iname "*.mov" -exec /path/to/myffmpeg.sh {} \;

Это вызовет скрипт оболочки один раз для каждого найденного файла. Сценарий оболочки, в свою очередь, извлекает имя файла из полного пути и вызывает ffmpegс соответствующими аргументами.


4

Я не получил решение, которое ожидалось, поэтому я нашел свое собственное. @ Даниэль ответит хорошо, но для этого нужен сценарий оболочки. Один лайнер быстрее, и мне нравится больше :), также более простое решение, чем написание скрипта.

Я мог бы использовать один аргумент и обработать его с basenameпомощью иsh -c

find . -iname "*.mov" -print0 | xargs -0 -i sh -c 'ffmpeg -i {} -f flv `basename {}`'

-I говорит xargs заменить {}текущим аргументом.
Вывод команды внутри `` распечатывается на стандартный вывод (функция bash), поэтому basename {}будет оцениваться как пустое имя файла и распечатываться.
-0 для правильной обработки специальных имен файлов, но вам нужно передать параметры с опцией -print0 с помощью find


3

Вы должны сделать это, как и все ответы, но ТОЧНОЕ использование xargs будет примерно таким:

echo argument1 argument2 argument3 | xargs -l bash -c 'echo this is first:$0 second:$1 third:$2' | xargs

Так что в вашем случае это будет:

find . -iname "*.mov" -printf "%p %f\n" | xargs -l bash -c 'echo ffmpeg -i $0 -f flv $1' | xargs

PS: Это ответ на вопрос о xargs для тех, кто ищет ответ именно для нескольких xargsпараметров в одной xargsкоманде.


1

Почему бы просто не переместить параметры ffmpeg, чтобы они соответствовали формату результатов команды find ?

find . -iname "*.mov" -printf "%p %f\n" | xargs -r -n2 ffmpeg -f flv -i

Обратите внимание на добавление опции -r к xargs, чтобы предотвратить запуск ffmpeg, если нет найдены файлы .mov .

Я добавил опцию -n2 в xargs, чтобы ограничить количество элементов, которые xargs обрабатывает до двух одновременно. В этом случае элементами являются путь к файлу и имя файла. Если не задана опция -n , xargs обработает как можно больше входных элементов за одно выполнение.


Это не будет работать, если найдено более одного файла AFAICT.
Даниэль Бек

Это работает только один раз для меня, но я не понимаю, почему это останавливается после первого. Любая идея ?
Kissgyorgy

на самом деле это не работает
kissgyorgy

Дэниел-Бек и @Walkman были правы насчет одиночной казни. Чтобы решить эту проблему, я отредактировал этот ответ, чтобы ограничить число элементов, которые xargs обрабатывает одновременно, с помощью опции -n2 . Без - N2 , xargs выполняется только один раз , если он может обрабатывать число входных элементов , которые он получает через трубу. Также следует отметить, что это решение работает только тогда, когда имена файлов и пути к файлам не содержат пробелов.
Застер

1

Я не уверен, можете ли вы или как это сделать с помощью xargs.

Но что-то вроде этого должно работать для вас:

find . -iname "*.mov" -printf "%p %f\n" | while read -a HR ; do echo ffmpeg -i ${HR[0]} -f flv ${HR[1]} ;done

1
Это не правильно обрабатывает пробелы в именах файлов / путях, не так ли?
Даниэль Бек

1

Альтернатива ответу Zoredache с использованием привязки имени (и с использованием различных разделителей, чтобы избежать проблемы пробелов в именах файлов):

IFS="\t" find -iname "*.mov" -printf "%p\t%f\n" | while read path file; do
    ffmpeg -i $path -f flv $file
done

Конечно, вы также можете использовать разделители с find -a arrayаргументом, использованным в другом ответе, но иногда именованные аргументы более понятны.


0

Вы можете запустить ffmpeg непосредственно из команды find следующим образом:

find . -iname "*.mov" -exec ffmpeg -i "%p" -f flv "%f" \;

Обратите внимание на кавычки вокруг параметров ffmpeg, если в имени файла есть пробелы, а экранированная точка с запятой отмечает конец выполненной команды.


Есть ли у вас документация по поведению -exec, которая также интерпретирует заполнители форматирования printf?
Даниэль Бек

Нет. Мозг пердеть: я думал, что% p и% f были находки, а не printf вещи. Я проголосовал за ваш ответ.
Рэнди Оррисон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.