아래 세 개에 표시된 것처럼 zip 파일 내에 중첩된 파일이 포함된 수천 개의 zip 파일을 포함하는 수백 개의 여러 폴더가 있습니다.
start tree structure
012016/
├── 2016-01
│ └── 2016-01
│ ├── build
│ ├── DOC
│ │ ├── WONWA1
│ │ │ ├── WO1NWA1
│ │ │ │ ├── WO2016000001NWA1.xml
│ │ │ ├── WO1NWA1.zip
│ │ │ ├── WO2NWA1
│ │ │ │ ├── WO2016000002NWA1_tr.xml
│ │ │ ├── WO2NWA1.zip
└── 2016-01.zip
end tree structure
아래에 폴더와 내용을 재귀적으로 확인하는 간단한 스크립트를 만들었습니다. zip 파일을 찾으면 내용을 추출한 다음 추출된 폴더의 내용을 확인합니다.
아래 스크립트를 실행하려고 하면:
recurse() {
for i in "$1"/*;
do
currentItem="$i"
extension="${currentItem##*.}"
if [ -d "$i" ]; then
#echo "dir: $i"
recurse "$i"
elif [ -f "$i" ]; then
#echo "file: $i"
#echo "ext: $extension"
[[ ${extension} = +(sh|xslt|dtd|log|txt) ]] && break
extractionDirectory=$(dirname $currentItem)/$(basename -s .zip $currentItem )
[[ ${extension} = "zip" ]] && unzip -uq $currentItem -d "${extractionDirectory}"
recurse ${extractionDirectory}
fi
done }
recurse $PWD
그러나 위 스크립트를 실행하면 다음과 같은 오류가 발생합니다.
분할 오류(코어 덤프)
답변1
분할 오류는 여러 가지 이유로 발생할 수 있습니다. 가장 일반적인 하위 수준 원인은 정의되지 않은 메모리 주소에 액세스하려는 프로세스, 즉 잘못된 포인터 역참조입니다. 이는 일반적으로 프로그램의 버그입니다.
여기서는 쉘 프로그램을 실행하고 있습니다. 셸은 고급 프로그래밍 언어이며 포인터가 없으므로 스크립트에서 잘못된 포인터 역참조가 발생할 수 없습니다.
많은 프로그램이 공간이 제한되어 있습니다.호출 스택스택 크기가 초과되어 발생한 분할 오류입니다. 대부분의 경우 스택 크기 제한은 합리적인 양의 데이터에 대해 충분히 크지만 무한 재귀로 인해 스택이 손상될 수 있습니다.
Bash에서 함수 호출의 무한 재귀는 실제로 분할 오류를 일으킬 수 있습니다. (dash와 mksh도 마찬가지입니다. ksh와 zsh는 더 똑똑하고 쉘 수준에서 최대 함수 호출 중첩 깊이를 적용하므로 세그폴트가 발생하지 않습니다.)
스크립트에 몇 가지 오류가 있습니다. 당신을 괴롭히는 것은 일반 파일의 경우 항상 recurse
zip 파일에 대해서만 호출하고 싶을 때 항상 마지막에 호출한다는 것입니다.
또는 을 의미할 때는 사용하지 마세요 &&
. 당신이 의미하는 바를 쓰는 것이 더 명확합니다. 모호함을 통한 간결함은 좋은 생각이 아니며 여기서는 당신을 귀찮게 합니다.||
if
if [[ ${extension} = "zip" ]]; then
unzip -uq $currentItem -d "${extractionDirectory}"
recurse ${extractionDirectory}
fi
또 다른 오류는 당신이 누락되었다는 것입니다변수 대체는 큰따옴표로 묶입니다., 따라서 프로그램은 무엇보다도 공백이 포함된 파일 이름을 차단합니다. 변수 대체를 생략해야 한다는 것을 알지 않는 한 항상 큰따옴표를 사용하십시오.
basename
및 를 호출하는 대신 매개변수 확장을 사용하세요 dirname
. 특수한 경우(예: 로 시작하는 파일 이름 -
)를 처리하는 것이 더 쉽고 빠릅니다.
내가 발견한 또 다른 버그는 패턴이 +(sh|xslt|dtd|log|txt)
분명히 의미하는 것입니다 @(sh|xslt|dtd|log|txt)
(이러한 확장자와 일치하는 shsh
등이 아님 dtdtxtshdtd
).
case
이는 일반적인 파일 상황입니다. 위의 오류는 수정되어 명확성을 위해 다시 작성되었습니다.
case "$extension" in
sh|xslt|dtd|log|txt) break;;
zip)
extractionDirectory=$"{currentItem%.zip}"
unzip -uq "$currentItem" -d "${extractionDirectory}"
recurse "${extractionDirectory}"
esac
논리를 확인하거나 코드를 테스트하지 않았습니다. 글을 쓰는 방법이 복잡해 보이는군요
find -type f -name '*.zip' -exec sh -c 'unzip -uq "$0" -d "${0%.zip}"' {} \;
답변2
~에서자일스의 대답:
Bash에서 함수 호출의 무한 재귀는 실제로 분할 오류를 일으킬 수 있습니다. (dash와 mksh도 마찬가지입니다. ksh와 zsh는 더 똑똑하고 쉘 수준에서 최대 함수 호출 중첩 깊이를 적용하므로 세그폴트가 발생하지 않습니다.)
Bash에서는 설정을 통해 최대 함수 호출 중첩 깊이를 설정할 수도 있습니다 FUNCNEST
. 이 위치는 다음과 같습니다 man bash
.
FUNCNEST 변수가 0보다 큰 값으로 설정되면 최대 함수 중첩 수준을 정의합니다. 제한을 초과하는 함수 호출로 인해 전체 명령이 중단됩니다.
여기에서 실제로 작동하는 모습을 볼 수 있습니다:
$ f () { f; }
$ FUNCNEST=10 f
bash: f: maximum function nesting level exceeded (10)