Bash 호출 및 배열

Bash 호출 및 배열

저는 bash 스크립팅을 처음 접했고 아직 초안이지만 이 스크립트는 예상대로 작동했습니다.

#!/bin/bash
find /var/www/site.com/ -type f -name "*.log" | xargs bash -c '
    
    for name; do

    parent=${name%/*}
    parent=${parent##*/}
    destdir=$(dirname $name)
    current_year=$(date +"%Y")

    if [[ "$name" =~ _([0-9]{4})- ]] &&
       [[ "$name" != *"$current_year"* ]]; then
         year="${BASH_REMATCH[1]}"
    else continue
    fi


    if [ ! -d "$destdir/$year/$parent" ]; then
         mkdir -p "$destdir/$year/"
    fi
          mv "$name" "$destdir/$year"

done '

find /var/www/site.com/ -type d -name "20*"  | xargs bash -c '

     for dir; do

     tar_name=$(echo $dir | grep -Eo '[0-9]{4}')
     tar cvfj '$tar_name'.tbz $dir 
done '
exit

보시다시피 bash 스크립트에서 bash를 두 번 호출했습니다. 이것은 나쁜 습관입니까? 말이 안 되나요/말이 안 되나요? 아니면 find 명령의 출력을 사용하여 배열을 만들고 반복하는 것이 더 낫습니까? 어떤 조언이라도 대단히 감사하겠습니다. 미리 감사드립니다. PS 들여쓰기가 부족해서 죄송합니다

답변1

내부 쉘 스크립트를 보지 않고도 몇 가지 참고할 사항이 있습니다.

파일 이름에 공백, 따옴표 또는 백슬래시 문자가 포함되어 있으면 일반 xargs작업이 실패합니다 . 여기에는 대부분의 다른 인용 규칙과 호환되지 않는 자체 인용 규칙 세트가 있습니다. (지금은 참고 질문을 찾을 수 없습니다.)

인라인 쉘 스크립트에 "0번째" 인수가 누락되어 첫 번째 파일 이름을 건너뛰게 됩니다.

또한 구문 강조 표시는 두 번째 명령이 깨졌음을 보여줍니다. grep -Eo '[0-9]{4}'전체 스크립트 주위에 작은 따옴표를 닫았다가 다시 여는 따옴표가 있습니다.


이제 이 문제는 xargs쉽게 해결되었으며 find ... -print0 | xargs -0 command...많은 구현(GNU, FreeBSD, Busybox)에서 이를 지원합니다.

0번째 매개변수 문제를 해결하려면 더미 매개변수( 로 끝나는 $0)를 추가해야 합니다.

... | xargs -0 bash -c '...' sh

또는 find ... -exec bash -c '...' sh {} +.

그러나 다른 쉘을 시작하지 않는 것이 좋습니다. Bash에서는 다음을 수행할 수 있습니다.

find  ... -print0 | while IFS= read -r -d '' file; do
    something with "$file"
done

또는,

while IFS= read -r -d '' file; do
    something with "$file"
done < <(find ... -print0)

후자는 루프 내부에 변수를 설정하고 루프 외부에서 변수를 사용할 수 있을 것으로 예상되는 경우에도 작동합니다.

관련 섹션 보기찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?(명령 대체를 사용하지 않으므로 모든 것이 관련이 있는 것은 아닙니다.)

출력을 find배열에 넣으려면 다음을 사용하십시오.

mapfile -t -d '' array < <(find ... -print0)

답변2

bash가 ≥4.3이라고 가정하면 호출 대신 재귀 와일드카드를 사용할 수 있습니다 find. find호출에는 아무런 문제가 없지만(올바르게 수행한 경우: 아래 참조) 재귀 와일드카드가 작동할 때는 덜 편리합니다. 전화해야 해shopt -s globstar재귀적 와일드카드를 활성화합니다.

shopt -s globstar

for name in /var/www/site.com/**/*.log; do
done

for dir in /var/www/site.com/**/20*/; do
done

하나를 사용하는 경우 파이프 로 find연결하지 마십시오 . 파일 이름을 구분하기 위해 다른 구문을 사용하므로 이름에 공백이 포함되어 있으면 셸 호출을 사용 하거나 .findxargs\'"-execfind … -print0 | xargs -0공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?더 많은 정보를 알고 싶습니다.

관련 정보