많은 수의 파일을 복사하는 동안 ‘인수 목록이 너무 깁니다’오류 xargs -I {} cp

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

\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는 쉘이 처리 할 수있는 것보다 긴 목록으로 확장됩니다. 대신 이것을 시도하십시오

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


답변

시스템 명령에 대한 인수 목록의 길이에는 최대 제한이 있습니다.이 제한은 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있습니다. 그러나 커널을 다시 컴파일하는 것은이 답변에서 설명하고자하는 것보다 더 많은 작업입니다.


답변

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

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


답변

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 프로그램 만 포크하면되므로 위 루프의 최적화입니다.


답변

프로그램에 지정할 수있는 최대 개수의 인수가 있으며 bash는 * .jpg를 cp에 대한 많은 인수로 확장합니다. find, xargs 또는 rsync 등을 사용하여 해결할 수 있습니다.

여기 xargs를 살펴보고 찾아보십시오

/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names


답변

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


답변

+옵션을 사용하면 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에 인수를 다시 정렬