-bash: /usr/bin/mv: 인수 목록이 너무 깁니다.

-bash: /usr/bin/mv: 인수 목록이 너무 깁니다.

이 명령을 사용할 때 mv * ..오류가 발생합니다 -bash: /usr/bin/mv: Argument list too long. 나는 이것이 발생하는 이유를 이해합니다. bash가 실제로 일치하는 모든 파일에 별표를 확장하여 매우 긴 명령줄을 생성하기 때문입니다. 이 오류를 어떻게 해결할 수 있나요?

답변1

제한은 bash가 아니라 execve()외부 명령을 실행하는 데 사용되는 시스템 호출에 있습니다. 당신은 할 수 있습니다 :

printf '%s\0' * | xargs -r0 mv -t .. --

printf에 내장되어 있으므로 그 시점에는 bash없습니다 . 그리고 그 한계를 피하기 위해 인수 목록을 분할하는 것이 작업 execve()입니다 . xargs여기서는 -tGNU의 GNU 특정 옵션을 사용합니다 mv.

를 사용하면 내장된 항목 zsh을 로드할 수 있습니다 mv.

zmodload zsh/files
mv -- * ..

또는 zargs도우미를 사용하여 분할을 수행합니다.

autoload -Uz zargs # best in ~/.zshrc
zargs -r -- ./* -- mv -t ..

./*with를 대체 ./*(D)하여 숨겨진 파일을 이동하거나 oNglob 한정자를 추가하여 파일 이름 정렬을 건너뛰거나 Nglob 한정자(with zargs -r)를 추가하여 일치하는 파일이 없는 경우 오류를 방지할 수 있습니다.

zargs -r -- ./*(ND) -- mv -t ..

동일:

print -rNC1 ./*(ND) | xargs -r0 mv -t ..

그러나 GNU에 대한 의존성은 없습니다 xargs.

Linux(일반적으로 Ubuntu에서 사용되는 커널)에서는 리소스 제한을 execve()높여 해당 제한을 늘릴 수도 있습니다 stacksize.

bash-5.1$ /bin/true {1..200000}
bash: /bin/true: Argument list too long
bash-5.1$ ulimit -s unlimited
bash-5.1$ /bin/true {1..200000}
bash-5.1$ 

완전히 무제한은 아닙니다(적어도 현재 버전의 커널에서는 아님).

bash-5.1$ /bin/true {1..2000000}
bash: /bin/true: Argument list too long

제한은 인수 및 에 전달된 환경 변수의 누적 크기에 따라 결정되지만 execve()계산은 단지 거기에 있는 바이트의 합계가 아니며 수행 방법은 OS와 버전에 따라 다릅니다.

답변2

두 개 이상의 단계로 수행할 수 있습니다.

mv [a-k]* ..    # or some other pattern matching a subset of the files
mv -- * ..

아니면 루프에서

for name in *; do
    mv -- "$name" ..
done

(그러나 이렇게 하면 mv각각의 이름이 개별적으로 호출됩니다.)

아니면 find도움을 받으세요:

find . -mindepth 1 -maxdepth 1 -exec mv -t .. -- {} +

이는 현재 디렉토리에서 모든 이름을 찾고 GNU를 사용하여 가능한 한 mv적은 호출로 위의 디렉토리로 이동합니다 .mv

GNU가 없지만 여전히 비표준 및 술어를 알고 있는 mva가 있으면find-mindepth-maxdepth

find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -- "$@" ..' sh {} +

이러한 변형 중 어느 것도 이름 충돌을 고려하지 않습니다. 올바르게 백업된 데이터를 테스트해야 합니다.

관련 정보