-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()해야 합니다 . GNU 의 GNU 특정 옵션이 xargs여기에서 사용됩니다 .-tmv

를 사용하면 내장된 항목을 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()계산은 단순히 바이트 합계 이상이며 수행 방법은 운영 체제 및 버전에 따라 다릅니다.

답변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는 없지만 mv여전히 find비표준 -mindepth-maxdepth조건자를 인식하고 있습니다.

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

이러한 변형 중 어느 것도 이름 충돌에 관심이 없습니다. 제대로 백업된 데이터로 테스트해야 합니다.

관련 정보