2013-08-28 2 views
1

xkcd #981의 상황을 에뮬레이트하는 빠른 쉘 스크립트를 작성하고 (하드 링크 및 상위 디렉토리에 심볼 링크 만 있음) 재귀 함수를 사용하여 모든 디렉토리를 작성했습니다. 불행하게도이 스크립트는 원하는 결과를 제공하지 않으므로 변수 $ count의 범위에 대한 내 이해가 잘못되었다고 생각합니다.쉘 스크립트 : 함수의 가변 범위

제대로 함수를 재귀를 사용하여 20 개의 폴더를 만들 수 있습니다. 각 폴더에는 3 개의 폴더 (3^20 폴더, 맨 위로 소프트 링크로 끝남)가 포함되어 있습니까?

#!/bin/bash 
echo "Generating folders:" 
toplevel=$PWD 
count=1 
GEN_DIRS() { 
for i in 1 2 3 
do 
     dirname=$RANDOM 
     mkdir $dirname 
     cd $dirname 
     count=$(expr $count + 1) 
     if [ $count < 20 ] ; then 
       GEN_DIRS 
     else 
       ln -s $toplevel "./$dirname" 
     fi 
done 
} 
GEN_DIRS 
exit 

답변

1

시도해보십시오 (스크립트의 수정 된 버전). 나는 20 레벨 깊이로 테스트를 거절한다. 8 단계의 깊이에서 3 개의 최상위 디렉토리 각각은 Mac 파일 시스템에서 약 50MB를 차지합니다.

#!/bin/bash 
echo "Generating folders:" 
toplevel=$PWD 
GEN_DIRS() 
{ 
    cur=${1:?} 
    max=${2:?} 
    for i in 1 2 3 
    do 
     dirname=$RANDOM 
     if [ $cur -le $max ] 
     then 
      (
      echo "Directory: $PWD/$dirname" 
      mkdir $dirname 
      cd $dirname 
      GEN_DIRS $((cur+1)) $max 
      ) 
     else 
      echo "Symlink: $PWD/$dirname" 
      ln -s $toplevel "./$dirname" 
     fi 
    done 
} 

GEN_DIRS 1 ${1:-4} 

라인 6과 7은 위치 매개 변수 ($1$2)에 이름을주는 것은 함수에 전달 - ${1:?} 표기는 단순히 매개 변수 $1을 통과 생략하면, 당신은에서 오류 메시지가 있음을 의미 쉘 (또는 서브 쉘)을 종료하고 종료합니다.

위 괄호 (13 행과 18 행)는 그 중간에있는 명령이 하위 셸에서 실행되므로 하위 셸 내의 디렉터리가 변경 되어도 상위 셸에 영향을주지 않습니다.

이제 11 행의 조건에서 < 문자열 대신 arithmetic (-le)을 사용합니다. 깊은 중첩을 위해 더 잘 작동합니다 (<은 사전 비교이므로 레벨 9는 레벨 10보다 작지 않습니다). 또한 [[ 명령 ([[도 사용할 수 있지만 [ 명령을 사용해도 괜찮습니다. 이전 방식을 선호합니다)을 의미합니다.

+0

여섯/일곱 한 나는 그것을 받아 4 개의 CUR 및 최대를 설정하는 라인? 또한, 왜 14-19 세의 약자입니까? 위대한 솔루션, 감사합니다! – CliffordSR

+0

불행히도 지금은 모든 디렉터리를 만들지 않습니다. 1과 20으로 호출하면 4 단계 깊이가 만들어지며 마지막 dir에는 3 대신에 하나의 심볼릭 링크가 생성됩니다./ – CliffordSR

+0

GEN_DIRS 호출에서 4 단계가 하드 코딩되었습니다. 1 대 3의 심볼릭 링크는 요구 사항에 대한 오해였습니다. 두 가지 문제가 모두 수정되었습니다. 'gendirs.sh'라는 스크립트로'bash gendirs.sh'를 실행하면 4 개의 레벨이 생성되고'bash gendirs.sh 8'은 8 개의 레벨을 생성합니다. –

0

나는이 같은 스크립트를 작성 결국 :

#!/bin/bash 

echo "Generating folders:" 

toplevel=$PWD 

level=0 
maxlevel=4 

function generate_dirs { 
    pushd "$1" >/dev/null || return 
    ((++level)) 
    for i in 1 2 3; do 
     dirname=$RANDOM 
     if ((level < maxlevel)); then 
      echo "$PWD/$dirname" 
      mkdir "$dirname" && generate_dirs "$dirname" 
     else 
      echo "$PWD/$dirname (link to top)" 
      ln -sf "$toplevel" "$dirname" 
     fi 
    done 
    popd >/dev/null 
    ((--level)) 
} 

generate_dirs . 

exit 
+0

완벽하게 작동하지만, 모든 것을 이해한다고 말할 수는 없습니다. 11 번 라인에 대해 설명해 주시겠습니까? 함수를 호출 한 인수를 삭제하고 있습니까? 그리고 함수의 마지막 두 줄은 왜? – CliffordSR

+0

또한 20 명이 생각했던 것보다 훨씬 오래 걸릴 것입니다 : P – CliffordSR

+0

@CliffordSR 자세한 정보는'help pushd'를보십시오. '>/dev/null'은 결과를 null로 보내 조용히합니다. 그리고'|| return '은 해당 디렉토리로 변경하지 못하면 함수를 종료합니다. 인수는 디렉토리입니다. 코드는 안전합니다. 원인을 알 수없는 이유로 실패하면 무한 루프가되거나 디렉토리가 아닌 것으로 간주됩니다. – konsolebox