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.