2017-11-12 11 views
0

다음과 같은 문제가 있습니다 :공백이있는 파일 이름을 처리 할 때 ""{} ""을 xargs로 전달해야하는 이유는 무엇입니까?

파일 찾기에 xargs-find 구조를 사용하고 싶습니다.

: 파일 이름은 자신의 이름 예를 들어

에 공백이있는 경우

command1 | xargs command2 

문제가 발생합니다 : 차이가 나는 지령 1로 찾을에서 Command2를 같이 사용하지 않는 것이있다 내가 시도하는 경우 :

echo 01.Here Comes The Night Time II.flac | xargs -pi find ~/Multimedia/Musik/flac/ -name "\""{}"\"" 

find ~/Multimedia/Musik/flac/ -name "01.Here Comes The Night Time II.flac" ?...yes 

아무것도 찾을 수 없습니다. 또한 xargs의 -0 옵션과 함께 작동하지 않습니다.

내가 복사 xargs를에서 대화 형 인쇄 요청을 붙여 넣을 경우

이 파일을 찾을 수 :

find ~/Multimedia/Musik/flac/ -name "01.Here Comes The Night Time II.flac" 

~/Multimedia/Musik/flac/Arcade Fire/Reflektor (CD 2)/01.Here Comes The Night Time II.flac 

내가 "공급"파이프 방식에 문제가있는, 또는 방법에 나는 포함 그런데 프로그램이 내부적으로 시작하는 방법 명령하면 쉘에 의해 해석에 관하여 ", 또는 뭔가 다른 (내가 시행 착오에 의해 파악) find 명령에?

+1

'... -name {}'은 어떻게됩니까? – melpomene

+1

"xargs -pi find ~/Multimedia/Musik/flac/-name {}"(-0 옵션없이) 명령을 사용하면 분명히 이것이 시도하지 않은 유일한 조합이었습니다. 그런데 왜 지금 일하고 있습니까? 이렇게하면 xargs의 명령 요청이 발생합니다. "find ~/Multimedia/Musik/flac/-name 01.Here Comes The Night Time II.flac"이 이에 대한 복사 및 붙여 넣기가 작동하지 않습니다. – madZeo

+0

무거운 손으로 제목을 편집하는 것을 용서하십시오. 그러나이 질문을 동일한 오해를 가진 다른 사람들에게로 향하게하는 첫 번째 접근법입니다. 그리고 질문에 정확히 답하는 것에 잠재적으로 관심이있는 사람들에게 명확하게 전달합니다. –

답변

2

당신은 혼란 것으로 보인다.

에서 유닉스, 프로그램을 시작하는 것은 세 가지 매개 변수를 포함한다. rs :

  1. 파일 이름. 이것은 실행할 프로그램의 경로를 포함하는 문자열입니다.
  2. 문자열 목록입니다. 규약에 따라이 "명령 행 인수"라고 부릅니다.
  3. 문자열의 다른 목록입니다. 규칙에 따라 우리는 이것을 "환경"이라 부릅니다. 그러나 OS 레벨에서 이것은 또 다른 문자열 목록 일뿐입니다. 그러나 모든 프로그램/라이브러리는 사용자와 응용 프로그램 프로그래머 모두에게 숨겨 지도록 유지합니다. 당신이 쉘에 명령을 입력 할 때

많은 일들이 발생하지만, 가장 간단한 경우는 공백으로 구분 된 단어의 단지 무리입니다 :

$ foo bar baz 

($은 쉘 프롬프트를 표시하지 뭔가 당신이 입력합니다.) 쉘은 세 단어 (foo, bar, baz)에이 줄을 분할하고 프로그램의 이름으로 첫 번째 해석

합니다 (PATH V에 나열된 디렉토리에서 조회 할 수 있습니다 ariable). PATH 목록이 /usr/bin이고 실제로는 /usr/bin/foo 프로그램이 있다고 가정 해 보겠습니다.

exec("/usr/bin/foo", ["foo", "bar", "baz"], [...]) 

즉 : (의사 코드) 다음과 같이

이제 쉘은 프로그램을 시작합니다 /usr/bin/foo에 실행 파일을 실행하고 인수로 세 개의 문자열 목록을 전달합니다. ( [...]은 지금부터 무시할 환경을 나타냅니다.)

이렇게하는 경우 어떻게됩니까?

$ foo "bar baz" 

따옴표는 셸이 줄을 단어로 분할하는 방식에 영향을줍니다. 특히 따옴표로 묶인 " " (공백)은 구분 기호로 사용되지 않고 그대로 사용됩니다. 이렇게하면 두 요소 목록 (foo, bar baz)이 표시됩니다. 따옴표는 단어 자체에 포함되지 않습니다.

는 내부적으로이 다음과 같은 호출로 변환 :

exec("/usr/bin/foo", ["foo", "bar baz"], [...]) 

가 다시 두 번째 인수는 단순히 공간을 포함하고 있습니다. 내장 된 따옴표가 없습니다.

그래서 무슨 일이

$ xargs -pi find ~/Multimedia/Musik/flac/ -name "\""{}"\"" 

같은 명령됩니까?

이것은 다시 셸에 의해 단어 목록으로 구문 분석됩니다. ~은 홈 디렉토리의 이름으로 바뀝니다. "\""은 단지 \" 또는 '"' (즉, 리터럴 " 문자)를 쓰는 회선 방식입니다. 우리가 끝내는 목록은 xargs, -pi, find, /home/madZeo/Multimedia/Musik/flac/, -name, "{}"입니다. 이것은 다음과 같은 호출로 변환 : 마지막 인수가 4 문자열 "{}" 얼마나

exec("/usr/bin/xargs", ["xargs", "-pi", "find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"{}\""], [...]) 

참고.

xargs은 첫 번째 인수 (-pi)를 옵션 사양으로 처리합니다. 특히 -i은 인수 목록의 {}을 표준 입력에서 읽은 현재 값으로 바꿔야한다고 알려줍니다.

xargs 그러면 표준 입력에서 한 행을 읽습니다.이 입력은 (echo 파이프이므로) 01.Here Comes The Night Time II.flac이됩니다.

이 목록 find, /home/madZeo/Multimedia/Musik/flac/, -name, "01.Here Comes The Night Time II.flac"을 산출 {} 대신에 대체됩니다. xargs는이 같은 find를 호출

exec("/usr/bin/find", ["find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "\"01.Here Comes The Night Time II.flac\""], [...]) 

이 이름이 그대로 " (견적 문자)로 시작하는 파일을 찾아 find을 알려줍니다. 그러한 파일이 없으므로 실패합니다.


수정은 다음과 같이 명령을 작성하는 것입니다 :

$ xargs -pi find ~/Multimedia/Musik/flac/ -name {} 

이 궁극적으로 당신이 원하는 인

exec("/usr/bin/find", ["find", "/home/madZeo/Multimedia/Musik/flac/", "-name", "01.Here Comes The Night Time II.flac"], [...]) 

를 실행 끝납니다.

xargs의 하위 명령 (이 경우 find)이 직접 실행됩니다. 쉘이 다시 파싱하는 새로운 명령 행을 생성하지 않습니다. 공백에 들어오는 인수를 분할하지 않고 따옴표를 해석하지 않고 $ 또는 * 또는 \과 같은 특수 문자는 신경 쓰지 않습니다. 주어진 단어의 목록을 취하고 서브 문자열 {}의 모든 항목을 현재 입력으로 바꾼 다음 실행합니다.

이 최종 명령을 천천히 취하여 쉘에 붙여 넣으면 단어 분리, 따옴표 제거 등을 수행하여 결과가 달라집니다.