it-swarm-ko.tech

`find`의 결과를 파일 목록으로 전달하는 방법은 무엇입니까?

상황은 MP3 플레이어가 있어요 mpg321는 파일 목록을 인수로받습니다. 내 음악을 "music"이라는 디렉토리에 보관합니다. 여기에 몇 개의 디렉토리가 더 있습니다. 모두 재생하고 싶기 때문에 프로그램을 실행합니다.

mpg321 $(find /music -iname "*\.mp3")

. 문제는 일부 파일 이름에 공백이 있고 프로그램이 해당 이름을 더 작은 부분으로 나누고 누락 된 파일에 대해 불평한다는 것입니다. find 결과를 따옴표로 묶기

mpg321 "$(find /music -iname "*\.mp3")"

모든 것이 하나의 큰 "파일 이름"이 될 것이기 때문에 도움이되지 않습니다.

그러면 어떻게 할 수 있습니까? 그게 중요하다면 bash을 사용하고 있지만 곧 zsh로 전환 할 예정입니다.

11
phunehehe

다음과 같이 xargs와 함께 find의 -print0 또는 -printf 옵션을 사용해보세요.

find /music -iname "*\.mp3" -print0 | xargs -0 mpg321

이것이 어떻게 작동하는지는 find 's manual page 에 의해 설명됩니다 :

-print0

진실; 표준 출력에 전체 파일 이름을 인쇄 한 다음 널 문자 (-print가 사용하는 개행 문자 대신)를 인쇄하십시오. 이렇게하면 줄 바꿈 또는 기타 유형의 공백이 포함 된 파일 이름이 찾기 출력을 처리하는 프로그램에서 올바르게 해석 될 수 있습니다. 이 옵션은 xargs의 -0 옵션에 해당합니다.

17
Steven D
find /music -iname "*\.mp3" -exec mpg123 {} +

GNU find를 사용하면 -print0xargs -0 사용할 수도 있지만 다른 도구를 배우는 데는별로 의미가 없습니다. -exec ... {} + 구문은 Linux가 -print0보다 늦게 획득했기 때문에 거의 언급되지 않았지만 지금은 사용하지 않을 이유가 없습니다.

Zsh 또는 bash 4를 사용하면 훨씬 간단합니다.

mpg123 **/*.[Mm][Pp]3

Zsh에서만 (a의 일부) 패턴을 대소 문자를 구분하지 않도록 만들 수 있습니다.

mpg123 (#i)**/*.mp3

Steven의 솔루션 이 최선이라고 생각하지만 다른 방법은 xargs '-I 플래그를 사용하는 것입니다. 그러면 명령에서 인수로 대체 될 문자열을 지정할 수 있습니다 명령 끝에 인수를 추가하면됩니다). 이를 사용하여 인수를 인용 할 수 있습니다.

find /music -iname "*\.mp3" | xargs -0 -Ifoo mpg321 "foo"
2
Michael Mrozek

일반적으로 직접 -exec ${tgt_process} \{\} +하는 것이 가장 좋지만 need 어떤 이유로 든 find에서 파일 또는 스트림에서 안정적으로 구분 된 파일 이름 목록을 가져 오면 이것을 할 수 있습니다 :

find -exec sh -c 'printf "///%s///\n" "[email protected]"' -- \{\} +

그로부터 얻는 것은 두 개의 nique 문자열입니다. 모든 파일 이름의 머리 부분에는 \n/// 문자열이 있고 모든 파일 이름의 끝 부분에는 ///\n 문자열이 있습니다. 이 두 문자열은 파일 이름에 포함 된 문자에 관계없이 해당 위치를 제외하고 find 출력의 다른 곳에서는 발생하지 않습니다.

또한 위의 사용법은 기본 POSIX 이식 가능하며 거의 모든 유닉스 시스템에서 작동하도록 신뢰할 수 있습니다. 이는 편의성에도 불구하고 다른 사람들이 권장하는 널 바이트 구분 기호의 사용에는 해당되지 않습니다.

그러나 다시 말하지만, 이것은 어떤 이유로 든 -exec 직접 $tgt_process 할 수없는 경우에만 필요합니다. 이것이 목표가되어야합니다. 우선 위의 방법은 여전히 ​​파싱이 필요합니다. 예를 들어, 각 파일 이름 Shell을 인용하려면 먼저 파일 이름의 하드 인용이 이스케이프되었는지 확인해야합니다.

find ... + | sed 's|'\''|&"&"&|g;s|///|'\''|g'

구성 문자가 무엇이든 상관없이 적절하게 쉘 이스케이프 된 파일 이름 배열을 출력합니다. 이제 수신 측의 응용 프로그램이 망가지지 않기를 바랍니다.

1
mikeserv

이를 수행하는 또 다른 방법은 파일 이름에 포함 된 모든 특수 문자를 이스케이프하는 것입니다. 예 :

find /music -iname "*\.mp3" | sed 's!\([] \*\$\/&[]\)!\\\1!g' | xargs mpg321

이것은 기본적으로 실행을 위해 적절하게 이스케이프 된 파일 이름을 xargs에 전달하며 문제가 없습니다.

0
Priyabrata Patnaik