使用nccopy循环压缩netcdf文件报Permission denied错误如何解决?
问题原因
- 输出文件路径构造错误:你代码中的
$i变量包含文件的相对路径(例如./subdir/wrfout_d04_2011-08-13_00:00:00),直接拼接d_${i}会生成d_./subdir/wrfout_d04_2011-08-13_00:00:00这类非法路径,系统会尝试在当前目录创建名为d_.的子目录写入文件,该目录不存在自然触发权限报错。单独执行命令时你大概率是先cd到对应文件所在目录后运行,输出文件名只有前缀没有多余路径,所以能正常执行。你给原文件设置777权限没有作用,因为报错不是读取原文件权限不足,是写入输出文件时路径非法导致的写入被拒绝。 - 循环遍历
find结果的写法存在缺陷:直接用for i in $(find ...)的方式会对文件名中的空格、换行、特殊符号做拆分,容易出现读取到的文件名不完整的问题,也可能引发执行异常。
修复方案
方案1:压缩后文件和原文件存储在同一目录(保留原目录结构)
推荐直接使用find的exec参数调用处理逻辑,避免路径解析问题:
find . -iname 'wrfout*' -type f -exec bash -c 'echo "$0"; time nccopy -d5 -s "$0" "${0%/*}/d_${0##*/}"' {} \;
其中${0%/*}用于提取文件所在的目录路径,${0##*/}用于提取不含路径的文件名本身,拼接后即可生成原文件同目录下加d_前缀的合法输出路径。
方案2:所有压缩后文件统一存放到当前工作目录(不保留原目录结构)
如果不需要保留子目录结构,所有输出文件都放在执行命令的目录下,可以用兼容特殊文件名的while read写法:
find . -iname 'wrfout*' -type f -print0 | while IFS= read -r -d '' file; do echo "$file" filename=$(basename "$file") time nccopy -d5 -s "$file" "d_${filename}" done
这里用-print0和read -d ''搭配,是为了兼容包含空格、换行等特殊字符的文件名,不会出现文件名拆分错误。
补充排查方法
如果修改路径后仍然报错,可以在nccopy命令前加strace -e openat定位具体权限问题:
strace -e openat nccopy -d5 -s 你的原文件路径 输出文件路径
运行后可以明确看到是读取原文件阶段还是写入输出文件阶段触发的权限错误,方便进一步定位问题。
内容的提问来源于stack exchange,提问作者ndichistan
相关产品推荐
相关产品推荐

