Làm thế nào tôi có thể sử dụng hai tham số cùng một lúc với xargs?


18

Tôi cần chuyển đổi video, nhưng tôi không biết chúng ở đâu, vì vậy tôi cần findchúng. Làm cách nào tôi có thể cung cấp kết quả và tên tệp đầu ra cho FFmpeg với xargs?

Tôi đã phát hiện ra rằng tôi có thể xây dựng hai tham số bằng lệnh này:

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

Tôi không thể tìm thấy bất cứ điều gì liên quan trong xargshướng dẫn. Tôi muốn một cái gì đó như thế này:

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

Tôi có thể làm cái này như thế nào?


Những người bạn vấp phải câu hỏi này bởi vì bạn đang tìm kiếm một câu trả lời về nhiều đối số xargs nói chung có thể muốn kiểm tra stackoverflow.com/questions/3770432/ .
Chris Oldwood

Câu trả lời:


4

Một cái gì đó như thế này sẽ thực hiện thủ thuật và bảo toàn đường dẫn đầy đủ, xử lý không gian, đổi tên folder/movie.movthành folder/movie.flv, v.v.

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

Và nếu tôi hiểu nhầm bạn và bạn muốn tất cả các phim .flv trong thư mục hiện tại, thay vào đó hãy sử dụng phim này:

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

3
Nếu bạn muốn nó như một oneliner, chỉ cần đặt mọi thứ trên một dòng. ;)
Mattias Ahnberg

9

Lý do mọi người sử dụng xargskết hợp với find là nhiều tên tệp sẽ được chuyển đến cùng một lệnh gọi chương trình của bất kỳ chương trình nào xargskhởi chạy. Ví dụ: nếu findtrả về các tệp foo , barbaz , phần sau đây sẽ mvchỉ chạy một lần:

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

Thực tế, nó gọi mvnhư sau:

mv -t destDir foo bar baz

Nếu bạn không cần hoặc muốn hành vi này (như tôi giả định là trường hợp ở đây), bạn chỉ có thể sử dụng find's -exec.


Trong trường hợp này, một giải pháp dễ dàng là viết một tập lệnh shell ngắn, như sau:

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

Lưu như myffmpeg.shvà chạy chmod +x myffmpeg.sh. Sau đó, chạy như sau:

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

Điều này sẽ gọi kịch bản shell một lần cho mỗi tệp được tìm thấy. Tập lệnh shell lần lượt trích xuất tên tệp từ đường dẫn đầy đủ và gọi ffmpegvới các đối số thích hợp.


4

Tôi đã không nhận được giải pháp mà tôi mong đợi, vì vậy tôi đã tự mình tìm ra. Câu trả lời của Daniel là tốt, nhưng nó cần một kịch bản shell. Một lớp lót nhanh hơn, và tôi thích nó hơn :) cũng là giải pháp đơn giản hơn viết kịch bản.

Tôi có thể sử dụng một đối số và xử lý nó với basenamevà sử dụngsh -c

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

-I nói với xargs để thay thế {}bằng đối số hiện tại.
Đầu ra lệnh bên trong `` được in ra đầu ra tiêu chuẩn (tính năng bash) vì vậy basename {}sẽ được đánh giá là tên tệp trần và được in ra.
-0 để xử lý tên tệp đặc biệt đúng cách, nhưng bạn cần truyền tham số với tùy chọn -print0 với find


3

Bạn phải làm điều đó giống như tất cả các câu trả lời trên đó, nhưng việc sử dụng chính xác các xargs sẽ giống như thế này:

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

Vì vậy, trong trường hợp của bạn, nó sẽ là:

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

PS: Điều này trả lời câu hỏi về xargs cho những người đang tìm kiếm một câu trả lời chính xác cho nhiều xargstham số trong một xargslệnh.


1

Tại sao không chỉ đơn giản là di chuyển các tùy chọn của ffmpeg để phù hợp với định dạng của kết quả từ lệnh find ?

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

Lưu ý việc thêm tùy chọn -r vào xargs để ngăn nó chạy ffmpeg nếu không tìm thấy tệp .mov .

Tôi đã thêm tùy chọn -n2 vào xargs để giới hạn số lượng các mục xargs xử lý thành hai lần. Trong trường hợp này, các mục là đường dẫn tệp và tên tệp. Nếu tùy chọn không -n được đặt, xargs sẽ xử lý càng nhiều mục đầu vào càng tốt trong một lần thực thi.


Điều này sẽ không hoạt động khi có nhiều hơn một tệp được tìm thấy AFAICT.
Daniel Beck

Điều này chỉ hoạt động một lần đối với tôi, nhưng tôi không hiểu tại sao nó dừng lại sau lần đầu tiên. Bất kỳ ý tưởng ?
Kissgyorgy

thực ra nó không hoạt động
Kissgyorgy

Daniel-Beck và @Walkman đã đúng về việc thực hiện đơn lẻ. Để giải quyết vấn đề đó, tôi đã chỉnh sửa câu trả lời này để giới hạn số lượng các mục xargs xử lý tại một thời điểm thông qua tùy chọn -n2 . Không có -n2 , xargs chỉ thực thi một lần nếu nó có thể xử lý số lượng mục đầu vào mà nó nhận được thông qua đường ống. Cũng cần chỉ ra rằng giải pháp này chỉ hoạt động khi tên tệp và đường dẫn tệp không bao gồm khoảng trắng.
ZaSter

1

Tôi không chắc chắn nếu bạn có thể hoặc làm thế nào để làm điều đó với xargs.

Nhưng một cái gì đó như thế này sẽ làm việc cho bạn:

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

1
Điều này không xử lý đúng không gian trong tên / đường dẫn tệp, phải không?
Daniel Beck

1

Một thay thế cho câu trả lời của Zoredache bằng cách sử dụng ràng buộc tên (và sử dụng các dấu phân cách khác nhau để tránh vấn đề khoảng trắng trong tên tệp):

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

Tất nhiên bạn cũng có thể sử dụng các dấu phân cách với find -a arrayđối số mà câu trả lời khác đã sử dụng, nhưng đôi khi các đối số được đặt tên là dễ hiểu hơn.


0

Bạn có thể chạy ffmpeg trực tiếp từ lệnh find như thế này:

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

Lưu ý các trích dẫn xung quanh các tham số cho ffmpeg, trong trường hợp có khoảng trắng trong tên tệp và dấu chấm phẩy thoát được đánh dấu kết thúc lệnh đã thực hiện.


Bạn có tài liệu cho hành vi của -exec cũng diễn giải các trình giữ chỗ định dạng printf không?
Daniel Beck

Không. Rối rắm não: Tôi đã nghĩ% p và% f là những thứ tìm thấy, không phải là những thứ in. Tôi đã bình chọn cho câu trả lời của bạn.
Randy Orrison
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.