찾기 + xargs : 인수 행이 너무 깁니다


21

다음과 같은 줄이 있습니다.

find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}

하지만 다음과 같은 오류가 발생했습니다.

xargs: argument line too long

혼란 스러워요. 를 사용 xargs하면이 문제를 정확하게 해결할 수 있습니까?

참고 : 기술적 -exec으로 찾기에 사용할 수 있다는 것을 알고 있지만 위의 실패 이유를 이해하고 싶습니다. 왜냐하면 xargs입력을 실행 가능한 인수로 관리 가능한 크기로 나누는 방법을 알고 있기 때문입니다. 이것이 사실이 아닙니까?

이것은 모두 zsh입니다.

답변:


11

글쎄, -i스위치는 더 이상 사용되지 않습니다.

-i[replace-str]
     This  option  is a synonym for -Ireplace-str if replace-str is specified. 
     If the replace-str argument is missing, the effect is the same as -I{}. 
     This option is deprecated; use -I instead.

그래서 당신의 명령을 이것으로 바꾸었을 때, 그것은 효과가있었습니다 :

$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}

$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...

사용 -I{}

이 명령 구문을 실행 한 이후에는이 방법을 사용하지 않아야합니다.

$ find -print0 ... | xargs -I{} -0 ...

암시 적으로 이러한 스위치를 켭니다 xargs, -x그리고 -L 1. -L 1를 구성하고는 xargs이 명령을 부르고 그래서 당신은 하나의 방식을 통해 파일을 실행합니다.

xargs1000 파일을 주면 mv명령을 1000 번 실행할 것이기 때문에 여기서는 사용 목적을 상실합니다 .

그렇다면 어떤 접근법을 사용해야합니까?

다음과 같이 xargs를 사용하여 수행 할 수 있습니다.

$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path

또는 그냥 모든 것을 찾으십시오.

$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +

감사! "This approach shouldn't be used"그렇다면 어떤 접근법을 대신 사용해야한다고 말했 을 때 ? 시겠습니까 "find /foot/bar/ -name '*.csv' -print0 | xargs -0 mv -t some_dir'"더 나은 솔루션이 될? 그렇다면, 어떻게 않습니다 xargs이 경우 알고 mv는 파이프에서 얻는 인수에 피드 명령? (항상 그것들을 마지막에 배치합니까?)
Amelio Vazquez-Reina

@ user815423426 - 그것을 수행하는 단지가 find ... -exec ...더 좋은 방법 또는 사용하려는 경우 xargs(가) find ... | xargs ... mv -t ...잘 너무. 그렇습니다 그것은 항상 그들을 마지막에 둡니다. 그렇기 때문에 그 방법에는 -t.
slm

5

옵션 -i은 선택적인 인수를 취합니다. 뒤에 공백을 넣었 으므로 옵션 -i에 대한 인수가 없었 -i으므로 후속 -0옵션은 옵션이 xargs아니라 6 개의 피연산자 중 두 번째입니다 {} -0 mv -t /some/path {}.

-ixargs 옵션 만 사용하면 줄 바꿈으로 구분 된 파일 이름 목록이 필요합니다. 입력에 줄 바꿈이 없었기 때문에 xargs는 널 파일이 포함 된 거대한 파일 이름을 받았지만 xargs는 확인하지 않았습니다. 전체 출력을 포함하는이 단일 문자열이 find최대 명령 행 길이보다 길어서 오류 "명령 행이 너무 깁니다".

귀하의 명령이 -i{}대신 작동했을 것입니다 -i {}. 또는 -I {}: -I과 유사 -i하지만 필수 인수를 사용할 수 있으므로 다음에 전달 된 다음 인수 xargs-I옵션 의 인수로 사용됩니다 . 그 후의 인수 -0는 옵션으로 해석됩니다.

그러나 전혀 사용해서는 안됩니다 -I {}. 사용 -I에는 세 가지 효과가 있습니다.

  • -I-0이미 처리 중인 견적 처리를 끕니다 .
  • -I바꿀 문자열을 변경하지만 {}기본값입니다.
  • -I각 입력 레코드에 대해 명령이 개별적으로 실행되도록합니다. 명령 ( mv -t)은 호출 당 여러 파일을 처리하기 위해 특별히 사용 되지 않으므로 여기서는 쓸모가 없습니다 .

떨어 뜨리 -I거나 -i완전히

find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}

또는 xargs를 삭제하고 다음을 사용하십시오 -exec.

find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +

0

bash for 루프를 사용해보십시오.

for FILE in *.mp4 ; do rm $FILE ; done

또는 무슨 일이 일어나고 있는지보고 싶다면 :

for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done

0

당신이 생선 껍질 을 사용하는 동안 이것을보고 있다면 .
이것은 물고기가 대체 문자열을 확장하는 방법과 관련이 있습니다.{}

당신이 물고기를 사용하는 경우 교체 문자열을 탈출해야합니다 \{\}

| xargs -I \{\} echo \{\}

또는 다른 교체 문자열을 사용하십시오

| xargs -I ! echo !
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.