Xargs ile aynı anda iki parametreyi nasıl kullanabilirim?


18

Videoları dönüştürmem gerekiyor, ama nerede olduklarını bilmiyorum, bu yüzden findonlara ihtiyacım var . Nasıl sonucu ve bir çıktı dosyası adını verebilir FFmpeg'den ile xargs?

Zaten bu komutu kullanarak iki parametreyi inşa edebileceğimi öğrendim:

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

xargsKılavuzda ilgili hiçbir şey bulamıyorum . Böyle bir şey istiyorum:

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

Bunu nasıl yapabilirim?


xargs Genel olarak ile birden fazla argüman hakkında bir cevap arıyorsanız, bu soruya rastlayanlar stackoverflow.com/questions/3770432/… ' a göz atmak isteyebilir .
Chris Oldwood

Yanıtlar:


4

Böyle bir şey hile yapmak ve tam yolu, sap alanı, yeniden adlandırma koruyacak folder/movie.movkadar folder/movie.flvvb

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

Seni yanlış anladıysam ve geçerli dizindeki tüm .flv filmlerini istiyorsanız, bunun yerine bunu kullanın:

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

3
Bir oneliner olarak istiyorsanız, her şeyi tek bir satıra koyun. ;)
Mattias Ahnberg

9

İnsanların xargsfind ile birlikte kullanmasının nedeni , birden çok dosya adının, başlatılan programın aynı program çağrısına geçirilmesidir xargs. Örneğin, finddöner dosyaları foo , bar ve Baz , şu çalışacak mvsadece bir kere:

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

Etkili, mvaşağıdaki gibi çağırır :

mv -t destDir foo bar baz

Bu davranışa ihtiyacınız yoksa veya istemiyorsanız (bence burada olduğu gibi), find's -exec.


Bu durumda, aşağıdaki gibi kısa bir kabuk betiği yazmak kolay bir çözüm olacaktır:

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

Farklı kaydet myffmpeg.shve çalıştır chmod +x myffmpeg.sh. Ardından, aşağıdakileri çalıştırın:

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

Bu, bulunan her dosya için kabuk komut dosyasını bir kez çağırır. Kabuk betiği dosya adını tam yoldan çıkarır ffmpegve uygun bağımsız değişkenlerle çağırır .


4

Beklediğim çözümü alamadım, bu yüzden kendim buldum. @ Daniel'in cevabı iyi, ama bir kabuk komut dosyasına ihtiyacı var. Bir astar daha hızlı ve ben daha iyi :) bir senaryo yazmaktan daha basit bir çözüm de seviyorum.

Bir argümanı kullanabilir ve onunla basenameve kullanarak işleyebilirimsh -c

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

-İ, xargs'a {}geçerli argümanla değiştirilmesini söyler .
Komut çıkışı içindeki `` standart çıktıya yazdırılır (bash özelliği) bu yüzden basename {}çıplak dosya adı olarak değerlendirilir ve yazdırılır.
Özel dosya adlarını düzgün bir şekilde işlemek için -0, ancak find ile -print0 seçeneğiyle parametreleri iletmeniz gerekir


3

Bunu tüm cevaplar gibi yapmalısınız, ama xargs'ın EXACT kullanımı şöyle olacaktır:

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

Yani sizin durumunuzda:

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

Not: Bu xargs, bir xargskomutta birden çok parametre için tam olarak cevap arayanlar için xargs ile ilgili soruyu cevaplar .


1

Neden ffmpeg seçeneklerini find komutundan sonuçların biçimine uyacak şekilde taşımıyorsunuz ?

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

Eklenmesini dikkat -r seçeneği Xargs çalışmasını engellemek için ffmpeg hiçbir eğer .mov dosya bulunur.

Eklediğim -N2 seçeneği Xargs öğelerinin sayısını sınırlamak için Xargs bir anda ikiye süreçler. Bu durumda, öğeler dosya yolu ve dosya adıdır. Hayır ise -n seçeneği ayarlandığında, Xargs tek bir yürütme olabildiğince çok sayıda giriş öğeleri olarak işleyecektir.


Bu, birden fazla dosya AFAICT bulunduğunda işe yaramaz.
Daniel Beck

Bu benim için sadece bir kez çalışıyor, ama neden birinciden sonra durduğunu anlamıyorum. Herhangi bir fikir ?
kissgyorgy

aslında çalışmıyor
kissgyorgy

Daniel-Beck ve @Walkman tek bir infaz konusunda haklıydılar. Bu sorunu çözmek için, xargs'ın -n2 seçeneği ile bir defada işlediği öğe sayısını sınırlamak için bu yanıtı düzenledim . Olmadan -N2 , xargs bu borunun içinde aldığı giriş öğe sayısı işleyebilir sadece bir kez yürütür. Ayrıca, bu çözümün yalnızca dosya adları ve dosya yolları boşluk içermediğinde çalıştığı da belirtilmelidir.
ZaSter

1

Bunu yapabileceğinizden veya xargs ile nasıl yapacağınızdan emin değilim.

Ancak bunun gibi bir şey sizin için çalışmalıdır:

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

1
Bu, dosya adlarındaki / yollarındaki boşlukları düzgün işlemez, değil mi?
Daniel Beck

1

Ad bağlama kullanarak Zoredache'nin cevabına bir alternatif (ve dosya adlarında boşluk oluşmasını önlemek için farklı ayırıcılar kullanarak):

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

Tabii ki ayırıcıları find -a arraydiğer cevabın kullandığı argümanla da kullanabilirsiniz , ancak bazen adlandırılmış argümanlar daha anlaşılır olabilir.


0

Ffmpeg aracını doğrudan find komutundan çalıştırabilirsiniz:

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

Dosya adında boşluk olması durumunda ffmpeg parametresinin etrafındaki tırnaklara dikkat edin ve kaçan noktalı virgül, yürütülen komutun sonunu işaretler.


Printf biçimlendirme yer tutucularını da yorumlayan -exec davranışı ile ilgili belgeleriniz var mı?
Daniel Beck

Hayır! Beyin osuruğu:% p ve% f'nin printf şeyler değil, find şeyler olduğunu düşünüyordum. Cevabınız için oy verdim.
Randy Orrison
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.