많은 수의 파일을 복사하는 동안 '인수 목록이 너무 깁니다'오류


12

다음 명령을 사용하고 있습니다.

\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/

그리고 오류가 발생합니다.

-bash: /bin/cp: Argument list too long

나는 또한 시도했다 :

ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/

여전히 -bash : / bin / ls : 인수 목록이 너무 깁니다.

아이디어가 있습니까?


하나의 디렉토리에서 다른 디렉토리로 모든 jpg를 복사하려고하지만 새로운 파일과 업데이트 된 파일 만 복사하려고합니다.
icelizard

ls이런 종류의 작업을 수행하도록 설계되지 않았습니다. 사용하십시오 find.
추후 공지가있을 때까지 일시 중지되었습니다.

문제는 ls가 아니라 쉘이 ls에 전달하는 인수의 수입니다. vi 또는 내장 명령이 아닌 경우에도 같은 오류가 발생합니다.
chris

그러나 ls됩니다 특히 이 작업을 수행하도록 설계되지 : mywiki.wooledge.org/ParsingLs을
추후 공지가있을 때까지 일시 중지.

사실이지만이 경우 오류는 ls의 구문 분석 오류로 인한 것이 아니라 ls가되는 새로운 프로세스에 10 억 개의 인수를 전달하는 것입니다. 부적절한 ls 사용 외에도 유닉스의 리소스 / 디자인 제한에 부딪치게됩니다. 이 경우 환자는 복통과 다리가 부러졌습니다.
chris

답변:


19

* .jpg는 쉘이 처리 할 수있는 것보다 긴 목록으로 확장됩니다. 대신 이것을 시도하십시오

find  /home/ftpuser/public_html/ftparea/ -name "*.jpg" -exec cp -uf "{}" /your/destination \;

find / home / ftpuser1 / public_html / ftparea / -name "* jpg"-exec cp -uf "{}"/ home / ftpuser2 / public_html / ftparea /를 사용하고 다음과 같은 오류가 발생했습니다.`-exec '에 대한 인수가 없습니다.
icelizard

당신은 cp의 마지막 인수가 빠져 있다고 대답했습니다. 구현을 다시 확인하십시오. 이 답변에서 "* .jpg"의 점이 누락되면 오작동이 발생할 수 있습니다 (cp는 "myjpg"라는 디렉토리). 참고 그 당신이 타입 파일을 사용하여 복사하는 것 (DIRS, 심볼릭 링크 방지 등의 영향에) 무엇을 긴밀하게 지정 paranoic하지만 안전 할 수 있습니다
drAlberT

면밀한 검사 후“\;”가 빠졌습니다. -exec가 실행해야하는 명령을 완료합니다. 바보 나!
icelizard

@AlberT : 누락 된 점을 다시 해 주셔서 감사합니다. 오타였습니다. 답변이 업데이트되었습니다.
Shawn Chin

cp가 처리 할 수있는 것은 아닙니다. 껍질은 할 수 없습니다.
d -_- b

6

시스템 명령에 대한 인수 목록의 길이에는 최대 제한이 있습니다.이 제한은 MAX_ARG_PAGES커널이 컴파일 될 때의 값을 기반으로 배포에 따라 다르며 커널을 다시 컴파일하지 않고는 변경할 수 없습니다.

쉘이 globbing을 처리하는 방식으로 인해 동일한 인수 ( "* .jpg")를 사용할 때 대부분의 시스템 명령에 영향을줍니다. glob가 먼저 쉘에 의해 처리 된 후 명령으로 전송되므로 명령은 다음과 같습니다.

cp -uf *.jpg /targetdir/

당신이 쓴 것처럼 쉘과 본질적으로 동일합니다 :

cp -uf 1.jpg 2.jpg ... n-1.jpg n.jpg /targetdir/

많은 jpeg를 다루는 경우 관리하기가 매우 빠릅니다. 이름 지정 규칙과 실제로 처리해야하는 파일 수 에 따라 한 번에 디렉토리의 다른 서브 세트 에서 cp 명령을 실행할 수 있습니다 .

cp -uf /sourcedir/[a-m]*.jpg /targetdir/
cp -uf /sourcedir/[n-z]*.jpg /targetdir/

이것은 효과적 일 수 있지만 파일 목록을 편리한 블록으로 얼마나 잘 나눌 수 있는지에 따라 정확히 얼마나 효과적입니까?

글로 블 가능. 나는 그 단어를 좋아한다.

findxargs 와 같은 일부 명령 은 크기가 큰 인수 목록을 만들지 않고도 큰 파일 목록을 처리 할 수 ​​있습니다.

find /sourcedir/ -name '*.jpg' -exec cp -uf {} /targetdir/ \;

간부 인수는 각 파일이 발견에 대해 한 번 명령 행의 나머지 실행됩니다 발견을 찾은 각 파일 이름으로 {} 대체. 때문에 CP의 명령은 한 번에 하나 개의 파일을 실행, 인수리스트의 제한은 문제가되지 않습니다.

각 파일을 개별적으로 처리해야하기 때문에 속도가 느려질 수 있습니다. xargs를 사용 하면보다 효율적인 솔루션을 제공 할 수 있습니다.

find /sourcedir/ -name '*.jpg' -print0 | xargs -0 cp -uf -t /destdir/

xargsfind 에서 제공하는 전체 파일 목록을 가져 와서 관리 가능한 크기의 인수 목록으로 분류 하고 각 하위 목록에서 cp 를 실행할 수 있습니다.

물론 커널을 다시 컴파일하여 더 큰 값을 설정할 수도 MAX_ARG_PAGES있습니다. 그러나 커널을 다시 컴파일하는 것은이 답변에서 설명하고자하는 것보다 더 많은 작업입니다.


나는 이것이 왜 투표에 실패했는지 전혀 모른다. 이것이 왜 일어나는지 설명하는 유일한 대답입니다. 아마도 xargs를 최적화로 사용하지 않는 것이 좋을까요?
chris

xargs 솔루션에 추가되었지만 여전히 downvotes가 내 세부 사항에서 끔찍한 문제로 인해 걱정되어 아무도 그것이 무엇인지 말하고 싶지 않습니다. :(
goldPseudo

xargs명령 호출의 결과 수가 훨씬 적기 때문에 훨씬 더 효율적인 것 같습니다. 필자의 경우 증가하는 파일 수를 가진 솔루션을 args사용할 때 6-12 배 더 나은 성능 -exec이 효율성을 높이는 것으로 나타났습니다.
Jan Vlcinsky

3

와일드 카드 식 ( *.jpg)이 확장 될 때 명령 줄 인수 길이 제한을 초과하기 때문에 (아마도 .jpg 파일이 많기 때문에 /home/ftpuser/public_html/ftparea) 발생합니다.

사용하는 것과, 그 제한을 우회하기위한 여러 가지 방법이있다 find거나 xargs. 이를 수행하는 방법에 대한 자세한 내용 은 이 기사 를 참조하십시오.


주제에 대한 외부 자원이 양호하면 +1
viam0Zah

3

GoldPseudo가 언급했듯이 생성중인 프로세스에 전달할 수있는 인수 수에는 제한이 있습니다. 해당 매개 변수에 대한 자세한 설명은 그의 답변을 참조하십시오.

프로세스에 너무 많은 인수를 전달하지 않거나 전달하는 인수 수를 줄이면 문제를 피할 수 있습니다.

쉘, 찾기 및 ls, grep 및 while 루프의 for 루프는이 상황에서 모두 동일한 작업을 수행합니다.

for file in /path/to/directory/*.jpg ; 
do
  rm "$file"
done

find /path/to/directory/ -name '*.jpg' -exec rm  {} \;

ls /path/to/directory/ | 
  grep "\.jpg$" | 
  while
    read file
  do
    rm "$file"
  done

모두 디렉토리 (쉘 자체, find 및 ls)를 읽는 하나의 프로그램과 실행마다 실제로 하나의 인수를 취하고 전체 명령 목록을 반복 하는 다른 프로그램을 가지고 있습니다.

이제 * .jpg 패턴과 일치하는 각 파일에 대해 rm을 분기하고 실행해야하므로 속도가 느려집니다.

이곳에서 xargs가 시작됩니다. xargs는 표준 입력을 취하고 모든 N (freebsd의 경우 기본적으로 5000) 행에 대해 N 개의 인수를 갖는 하나의 프로그램을 생성합니다. xargs는 명령 행에서 인수를 읽는 전체 파일 세트를 반복하기 위해 1 / N 프로그램 만 포크하면되므로 위 루프의 최적화입니다.



1

'*'글로브가 너무 많은 파일 이름으로 확장되고 있습니다. 대신 find / home / ftpuser / public_html -name '* .jpg'를 사용하십시오.


찾기 및 반향 * 결과는 동일한 출력을 나타냅니다. 여기서 핵심은 10 억 개의 명령 줄 인수를 모두 쉘이 포크하려고하는 명령에 전달하는 것이 아니라 xargs를 사용하는 것입니다.
chris

파일이 너무 많으면 echo *가 실패하지만 찾기는 성공합니다. 또한 +와 함께 find -exec를 사용하는 것은 xargs를 사용하는 것과 같습니다. (모두 지원 +를 찾을 수는 없습니다)
William Pursell

1

+옵션을 사용하면 find -exec작업 속도가 크게 향상됩니다.

find  /home/ftpuser/public_html/ftparea/ -name "*jpg" -exec cp -uf -t /your/destination "{}" +

+옵션은 {}마지막 인수 여야하므로 -t /your/destination(또는 --target-directory=/your/destination) 옵션을 cp사용하여 작동 시키십시오.

보낸 사람 man find:

-exec 명령 {} +

          This  variant  of the -exec action runs the specified command on  
          the selected files, but the command line is built  by  appending  
          each  selected file name at the end; the total number of invoca  
          tions of the command will  be  much  less  than  the  number  of  
          matched  files.   The command line is built in much the same way  
          that xargs builds its command lines.  Only one instance of  ‘{}’  
          is  allowed  within the command.  The command is executed in the  
          starting directory.

편집 : cp에 인수를 다시 정렬


'-exec'에 대한 인수 누락 / home / ftpuser1 / public_html / ftparea / -name '* jpg'-exec cp -uf "{}"/ home / ftpuser2 / public_html / ftparea / +
icelizard

cp그 오류를 해결하기 위해 인수를 재정렬했습니다 .
추후 공지가있을 때까지 일시 중지되었습니다.

1

*.jpg해당 디렉토리에 파일 이 너무 많아서 한 번에 명령 행에 모두 넣을 수없는 것 같습니다. 시도해 볼 수 있습니다 :

find /home/ftpuser/public_html/ftparea1 -name '*.jpg' | xargs -I {} cp -uf {} /home/ftpuser/public_html/ftparea2/

스위치가 시스템에 적합한 man xargs지 확인하려면 구현 을 확인해야 할 수도 -I있습니다.

실제로, 해당 파일을 이미있는 동일한 위치에 복사하려고합니까?


사과이 두 디렉토리는 ftpuser1과 ftpuser2 여야합니다.
icelizard

방금 시도한 사항 : ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} / home / ftpuser2 / public_html / ftparea / 여전히 -bash : / bin / ls : 인수 목록이 너무 깁니다.
icelizard

아, 맞습니다. 물론 ls같은 문제가 있습니다! 나는 find그렇지 않은 것으로 바꿨다 .
Greg Hewgill

0

폴더로 이동

cd /home/ftpuser1/public_html/

다음을 실행하십시오.

cp -R ftparea/ /home/ftpuser2/public_html/

이러한 방식으로 'ftparea'폴더에 하위 폴더가있는 경우 '* .jpg'파일 만 원할 경우 부정적인 영향을 줄 수 있지만 하위 폴더가없는 경우이 방법이 훨씬 더 빠릅니다. find와 xargs 사용

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