Як я можу використовувати два параметри одночасно за допомогою 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у поєднанні з знахідкою, полягає в тому, що кілька імен файлів будуть передані одній і тій самій виклику програми будь-якого 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 виконується тільки один раз , якщо він може обробляти число вхідних елементів , які він отримує через трубу. Слід також зазначити, що це рішення працює лише тоді, коли назви файлів та шляхи до файлів не містять пробілу.
ZaSter

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

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

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.