쉘 스크립트에서 하나의 작업을 완료한 후 변수에 다른 값을 어떻게 할당합니까?

쉘 스크립트에서 하나의 작업을 완료한 후 변수에 다른 값을 어떻게 할당합니까?

디렉토리가 존재하는지 확인하고 이름/경로를 기반으로 그 아래의 모든 내용을 압축하는 스크립트를 만들려고 합니다.

내가 갈 수 있는 가장 먼 곳은——

#!/system/bin/sh -xv

Z="$PWD/../WorkingDir";
T='320';
F='480';
I='540';
D='dark';
L='light';
P='play';

cd $Z;

if [ -d $T/$D ]; then
    R=""$T"_"$D".zip";
else
    if [ -d $T/$L ]; then
        R=""$T"_"$L".zip";
    else
        R="file.zip";
    fi
fi;

for dir in */*/; do
    #Skip directories where the zip already exists
    [ -e "$dir"/"$R" ] || 
    ( cd -- "$dir" && zip -0rq "$R" .)
done

그런데 이런 일이 일어났어요 -

#!/system/bin/sh -xv
...
.
.
if [ -d $T/$D ]; then
    R=""$T"_"$D".zip";
else
    if [ -d $T/$L ]; then
        R=""$T"_"$L".zip";
    else
        R="file.zip";
    fi
fi;
+ [ -d 320/dark ]
+ R=320_dark.zip

for dir in */*/; do
    #Skip directories where the zip already exists
    [ -e "$dir"/"$R" ] ||
    ( cd -- "$dir" && zip -0rq "$R" .)
done
+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_dark.zip ]
+ cd -- 320/light/
+ zip -0rq 320_dark.zip .
.
.
...and so on..

각 파일의 이름은 동일합니다(320_dark.zip이 경우). 각 압축 파일이 폴더 이름/경로에 따라 다르기를 원합니다.

나는 생각했다 -

+ [ -d 320/dark ]
+ R=320_dark.zip

- 매번 모든 폴더를 변경하십시오. 320_light.zip폴더 경로가 이어야 하는 것처럼 320/light.

따라서 출력의 마지막 부분은 -

+ [ -e 320/dark//320_dark.zip ]
+ cd -- 320/dark/
+ zip -0rq 320_dark.zip .
+ [ -e 320/light//320_light.zip ]
+ cd -- 320/light/
+ zip -0rq 320_light.zip .

답변1

일관성을 위해 단일 문자 변수를 제거하고 아카이브 위치를 변경하는 것이 좋습니다.

#!/system/bin/sh -xv

cd "$PWD/../WorkingDir"

compress() {
    # Detect only known dir names, convert slash to underscore
    local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"

    # Set a default value to the variable
    : ${arch:=file}

    # Only create a ZIP archive if not present in the parent directory
    # Note $PWD is evaluated *before* cd
    [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
}

for dir in */*/; do
    compress $dir
done

해당 행을 변경하여 sed"잘 알려진 디렉토리 이름"을 추가하십시오.


편집하다: OP의 요청에 따라 설명을 추가합니다.

루프가 새 디렉터리를 찾을 때마다 스크립트는 디렉터리를 압축하기 전에 조건을 확인합니다 for. 변수도 제거됩니다. 코드를 분석해 보겠습니다.

메인 루프

cd "$PWD/../WorkingDir"

for dir in */*/; do     # Ensures to select only directories
    compress $dir       # compress runs some checks prior to compressing
done

이것에 대해서는 별로 할 말이 없습니다.

compress루틴

local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"

$1compressed즉, 검사하고 압축할 디렉터리 로 전달되는 매개변수입니다 . sed먼저 ( '/320\/(light|dark)/') 경로가 다음 형식인지 확인하십시오.

320/light
320/dark

그리고 슬래시가 밑줄로 변환된 경로를 반환합니다 's@/@_@g'. 가독성을 높이고 슬래시가 이스케이프되는 것을 방지하려면 at 기호를 구분 기호로 사용하세요. 다른 유효한 기호는 's:/:_:g'or 's#/#_#g'또는 classic 입니다 's/\//_/g'. 변환하려는 슬래시를 이스케이프 처리하기 위해 백슬래시를 사용하는 방법에 유의하세요. 나는 후자의 형식이 읽기 어렵다고 생각합니다.

; p와 함께 사용되는 후행 sed -n이 특별한 경우 후자의 옵션은 "p일치하는 항목이 발견되지 않는 한(예: 슬래시로 둘러싸인 경우) 아무 것도 에코하지 마세요.». 따라서 arch슬래시가 포함된 경로는 밑줄로 변환됩니다.만약에 그리고 만약에320\/(light|dark)경로에서 정규식을 찾으세요. 그렇지 않으면 아무것도 에코하지 않고 arch빈 변수를 형성합니다.

Option은 더 읽기 쉬운 표준 정규 표현식의 사용을 알려주는 -r편리한 방법 입니다. sed그렇지 않으면 대괄호와 파이프 문자를 이스케이프해야 합니다. 나는 '/320\/(light|dark)/s@/@_@gp'or보다 더 읽기 쉽다고 생각합니다.'/320\/\(light\|dark\)/s@/@_@gp''/320\/\(light\|dark\)/s/\//_/gp'

: ${arch:=file}

행이 비어 있으면 arch기본값인 "file"로 설정됩니다. 이 이상한 구성은 ${arch:=file}단독으로 구성하면 구문 오류가 발생하기 때문에 필요합니다 . 콜론은 쉘에게 아무 작업도 수행하지 않고( ) :비어 있으면 값을 할당하도록 지시합니다.arch

    [ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )

여기서는 전자가 길이가 0인 파일도 확인하기 때문에 -fnot을 사용했습니다 . -e테스트는 ZIP 아카이브가 존재하는 경우에만 성공합니다.그리고길이가 0이 아닙니다.

부모(또는 스크립트의현재의) 디렉터리이거나 크기가 null인 경우 스크립트는 인수로 전달된 디렉터리를 변경 compress하고 해당 내용을 압축하는 하위 쉘을 생성합니다. 변수 $1$PWD가 평가됩니다.앞으로서브쉘은 초기 버전의 상위 디렉토리 $PWD와 동일한 명령을 실행합니다 .$Z

필터 확장

방법은 다음과 같습니다 sed.

sed -rne '/320\/(light|dark|play)/s@/@_@gp'

디렉토리 이름을 확인하세요.

320/light
320/dark
320/play

또한 9개의 조합 또는 보다 일반적인 형식 (모든 숫자 뒤에 슬래시와 "1"이 붙음)을 /(320|480|540)\/(light|dark|play)/제공한다고 생각할 수도 있습니다./[0-9]+\/(light|dark|play)/","어두운" 그리고"놀다") 또는 짝수 /[0-9]+\/\w+/(슬래시와 단어가 뒤따르는 임의의 숫자, 일명 [A-Za-z0-9_]+). 이는 필터를 얼마나 엄격하게 또는 넓게 설정하려는지에 따라 달라집니다.

답변2

#!/system/bin/sh -xv

Z=/absolute/path/to/WorkingDir
T=320
F=480 # ?
I=540 # ?
D=dark
L=light
P=play # ?

cd $Z

for dir in $Z*/*/; do

    if [ -d $Z/$T/$D ] && [ ! -f $T$D.zip ]; then
        zip -0rq $T$D.zip $dir;            
    elif [ -d $Z/$T/$L ] && [ ! -f $T$L.zip ]; then      # elif rules
        zip -0rq $T$L.zip $dir;
    # It's not very efficient to scale this up, but you could add more elif statements here.
    elif [ -d $Z/$F/$D ] && [ ! -f $F$D.zip]; then
        zip -0rq $F$D.zip $dir;
    # and so on..
    else
        exit
    fi;
done

나는 그것이 당신에게 필요한 것이라고 생각합니다. 조정이 필요한 경우 알려주시기 바랍니다.

관련 정보