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/… 을 확인하고 싶을 수도 있습니다 .
Chris Oldwood

답변:


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
원 라이너로 원한다면 모든 것을 한 줄에 넣으십시오. ;)
Mattias Ahnberg 2012 년

9

사람들 xargs이 find와 함께 사용하는 이유 는 여러 파일 이름이 프로그램이 xargs시작될 때마다 동일한 프로그램 호출로 전달되기 때문 입니다. 예를 들어 foo , barbazfind 파일을 반환 하면 다음이 한 번만 실행 됩니다.mv

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

효과적으로 mv다음과 같이 호출됩니다 .

mv -t destDir foo bar baz

당신이 할 필요는 없다을하거나 (여기의 경우 가정으로)이 동작을 원한다면, 당신은 간단하게 사용할 수있는 find'들 -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

나는 예상했던 해결책을 얻지 못했기 때문에 내 자신을 알았습니다. @Daniel의 대답은 좋지만 쉘 스크립트가 필요합니다. 하나의 라이너가 더 빠르며 스크립트를 작성하는 것보다 더 나은 솔루션이 더 좋습니다.)

하나의 인수 basename를 사용하여 처리하고 사용할 수 있습니다.sh -c

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

-i는 xargs에게 {}현재 인수 로 대체하도록 지시합니다 .
''안의 명령 출력은 표준 출력 (bash 기능) basename {}으로 인쇄되므로 기본 파일 이름으로 평가되어 인쇄됩니다.
특수 파일 이름을 올바르게 처리하려면 -0이지만 find와 함께 -print0 옵션을 사용하여 매개 변수를 전달해야합니다.


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

추신 : 이것은 xargs하나의 xargs명령으로 여러 매개 변수에 대한 정답을 정확하게 찾는 사람들을 위해 xargs에 대한 질문에 대답합니다 .


1

find 명령 의 결과 형식에 맞게 ffmpeg 의 옵션을 단순히 이동하지 않는 이유는 무엇 입니까?

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

.mov 파일이 없으면 ffmpeg 가 실행되지 않도록 xargs-r 옵션을 추가하십시오 .

xargs-n2 옵션을 추가하여 xargs 프로세스 수를 한 번에 2 개로 제한했습니다 . 이 경우 항목은 파일 경로와 파일 이름입니다. -n 옵션을 설정 하지 않으면 xargs 는 단일 실행에서 가능한 많은 입력 항목을 처리합니다.


AFAICT에서 두 개 이상의 파일을 찾으면 작동하지 않습니다.
Daniel Beck

이것은 나에게도 한 번만 작동하지만 첫 번째 후에 왜 멈추는 지 이해할 수 없습니다. 어떤 아이디어?
kissgyorgy

실제로 작동하지 않습니다
kissgyorgy

Daniel-Beck과 @Walkman은 단일 실행에 대해 정확했습니다. 이 문제를 해결하기 위해 -n2 옵션을 통해 xargs 프로세스 항목을 한 번에 제한하도록이 답변을 편집했습니다 . 포함하지 않는 -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
이것은 파일 이름 / 경로의 공백을 올바르게 처리하지 못합니까?
Daniel Beck

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

다음과 같이 find 명령에서 ffmpeg를 직접 실행할 수 있습니다.

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

파일 이름에 공백이 있고 이스케이프 된 세미콜론이 실행 된 명령의 끝을 표시하는 경우 매개 변수를 ffmpeg로 인용하십시오.


printf 형식 자리 표시자를 해석하는 -exec의 동작에 대한 설명서가 있습니까?
Daniel Beck

아니. 뇌 방귀 : % p와 % f는 printf-things가 아니라 find-things라고 생각했습니다. 귀하의 답변에 투표했습니다.
랜디 올리 슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.