我有数百个多个文件夹,其中包含数千个 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
造成分段错误的原因有很多。最常见的低级原因是进程试图访问未定义的内存地址,即无效的指针取消引用。这通常是程序中的错误。
在这里,您正在运行一个 shell 程序。 shell 是一种高级编程语言,没有指针,因此您的脚本不会导致无效的指针取消引用。
许多程序的空间有限调用栈分段错误的死因是超出了堆栈大小。在大多数情况下,堆栈大小限制对于任何合理的数据来说都足够大,但无限递归可能会破坏堆栈。
在 bash 中,函数调用中的无限递归确实会导致分段错误。 (dash 和 mksh 也是如此;ksh 和 zsh 更聪明,并且在 shell 级别应用最大函数调用嵌套深度,这样它们就不会出现段错误。)
您的脚本有几个错误。令您困扰的是,对于常规文件,您总是recurse
在最后调用,而您显然只想对 zip 文件执行此操作。
当您的意思是 时,不要使用&&
or 。写出你的意思就更清楚了;通过晦涩难懂来简洁并不是一个好主意,它在这里让你感到困扰。||
if
if [[ ${extension} = "zip" ]]; then
unzip -uq $currentItem -d "${extractionDirectory}"
recurse ${extractionDirectory}
fi
另一个错误是你失踪了变量替换用双引号引起来,因此您的程序将因包含空格(以及其他)的文件名而阻塞。始终在变量替换周围使用双引号,除非您知道需要将其省略。
使用参数扩展而不是调用basename
and 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 更聪明,并且在 shell 级别应用最大函数调用嵌套深度,这样它们就不会出现段错误。)
在 Bash 中,您还可以通过设置来设置最大函数调用嵌套深度FUNCNEST
。这在man bash
:
如果将 FUNCNEST 变量设置为大于 0 的数值,则定义最大函数嵌套级别。超过限制的函数调用会导致整个命令中止。
您可以在这里看到它的实际效果:
$ f () { f; }
$ FUNCNEST=10 f
bash: f: maximum function nesting level exceeded (10)