`$RANDOM`은 `find`의 `-exec`에서 무작위가 아닙니다.

`$RANDOM`은 `find`의 `-exec`에서 무작위가 아닙니다.

Linux 시스템에서 여러 폴더를 찾아 이동하려고 합니다.

모든 폴더의 이름은 동일하므로 echo $RANDOM폴더 이름으로 임의의 숫자를 제공합니다.

echo $RANDOM
실제로 실행될 때마다 난수가 출력됩니다. 그러나
find . -type d -name .AppleDouble -exec mv \'{}\' \'/raid/data/Storage/AppleDouble/`echo $RANDOM` \;
각 폴더에 동일한 "임의" 번호를 사용하므로 하나의 폴더만 이동됩니다.

$RANDOM문제는 달리기 시작하자마자 평가하는 것 같아요 . 옵션이 실행되기 전에 값이 계산되지 않도록 find이스케이프 처리하려면 어떻게 해야 합니까 (또는 이를 수행하는 더 좋은 방법은 무엇입니까)?$RANDOM-exec

참고: 나는 busybox에 있어서 아무것도 설치할 수 없습니다.

답변1

당신 말이 맞습니다. 인용하지 않았기 때문에 find명령줄을 작성할 때 쉘에 의해 평가됩니다. 하지만 일반적으로 -exec사용 되지는 않으므로 bash작은따옴표로 인용하거나 이스케이프 처리하면 $전혀 확장되지 않습니다.

bash해결책은 내부적으로 호출하는 것입니다 -exec.

find . -type d -name .AppleDouble -exec bash -c 'echo $RANDOM' \;

답변2

실행 중인 명령에 몇 가지 문제가 있습니다.

mv \'{}\' \'/raid/data/Storage/AppleDouble/`echo $RANDOM`

`echo something`동일합니다 something( something일부 특수 문자가 포함되지 않는 한, 이 경우 추가 및 명령 대체 효과로 인해 echo일반적으로 상황이 더 악화됩니다). 그래서 쓰는 방법이 복잡하네요

mv \'{}\' \'/raid/data/Storage/AppleDouble/$RANDOM

따라서 셸은 find위에 표시된 명령줄 부분의 명령 에 mv, '{}'및 의 세 가지 인수를 전달합니다. '/raid/data/Storage/AppleDouble/12345여기서 는 12345임의의 값입니다. 특수 변수의 값은 RANDOM호출 전에 셸에 의해 확장되므로 find실행되는 모든 명령은 find동일한 값으로 실행됩니다. 또한 파일 이름의 일부가 될 추가 작은따옴표가 있다는 점에 유의하세요. 그냥 제거하세요.

모든 호출을 확장 하고 싶기 때문에 직접 실행하는 대신 실행할 쉘을 실행하도록 $RANDOM알려야 합니다 .findmvfindmv

find . -type d -name .AppleDouble -exec sh -c 'mv "$0" /raid/data/Storage/AppleDouble/$RANDOM' {} \;

참고하시기 바랍니다,충돌 확률난수는 매우 높습니다. 최대 2 15$RANDOM 까지만 가능하므로 213개 이상의 파일을 복사하는 경우 두 파일이 동일한 대상에 복사될 확률은 50% 이상입니다. 이 상황에서 임의의 이름을 사용하는 것은 매우 나쁜 생각입니다. 대신 다음 이름을 사용하십시오.독특함을 보장합니다각 소스 파일에 대해. 한 가지 방법은 소스 경로의 암호화 해시를 사용하는 것입니다.

find . -type d -name .AppleDouble -exec sh -c 'mv "$0" /raid/data/Storage/AppleDouble/$(echo "$0" | md5sum | cut -d " " -f 1)' {} \;

답변3

문제가 정확히 무엇인지 잘 모르겠습니다.

나는 마침내 포기하고 finds 에 전달할 외부 스크립트를 작성했는데 -exec작동하는 것 같았습니다.

왜 전체 명령을 한 줄에 넣을 수 없는지 잘 모르겠습니다. 내가 사용하고 있는 busybox와 bash 버전에는 이상한 버그가 있는 것 같습니다.오래된둘 다의 버전. 2006년에 출시된 busybox 1.1.0과 비슷한 시기의 bash 3.00.16입니다(bash 출시 이력을 찾을 수 없습니다).

관련 정보