Shell脚本中mv命令报错No such file or directory求助排查
解决
mv: cannot stat 'tmp': No such file or directory 错误 & 脚本优化 我帮你分析下脚本里的问题,这个错误主要是几个明确的问题点导致的,我们一步步来修复:
1. 直接触发错误的多余 mv 命令
看你脚本里这一行:
#Escaping and cleanup mv tmp $currentFile
这一行前面没有任何生成tmp文件的操作,之前的sed命令都已经通过&& mv tmp $currentFile完成了临时文件的替换,所以这里的tmp根本不存在,执行这行必然报错。直接删掉这一行就能解决这个即时错误。
2. eval 使用不当导致的潜在 tmp 生成失败
你的SED_ARG变量里的引号嵌套逻辑有问题,比如:
SED_ARG=" 's/fid=\"${fidMap[$field]}\">.*/fid=\"${fidMap[$field]}\">$newValue<\/$field>/'" $currentFile eval sed $SED_ARG > tmp && mv tmp $currentFile
这种写法很容易因为变量里的特殊字符(比如newValue含空格、引号)导致sed命令执行失败,进而tmp文件没生成,后续mv同样会报错。我们可以去掉eval,改用sed的原地修改参数-i,既安全又能避免临时文件的mv操作:
把原来的if-else块改成:
grep "<$field" "$currentFile" >/dev/null if [ $? -eq 0 ]; then sed -i.bak "s/fid=\"${fidMap[$field]}\">.*/fid=\"${fidMap[$field]}\">$newValue<\/$field>/" "$currentFile" rm "${currentFile}.bak" # 删除sed自动生成的备份文件 else sed -i.bak "s/<\/issue>/<$field fid=\"${fidMap[$field]}\">$newValue<\/$field> <\/issue>/" "$currentFile" rm "${currentFile}.bak" fi
3. 脚本开头的return 0错误
在脚本顶层使用return是不符合shell语法规范的,return是用于函数内返回的,脚本退出应该用exit:
if [ "$1" = "" ] || [ "$2" = "" ] || [ "$3" = "" ]; then echo "Please pass in three variables: issueNumber field value" echo "Example: new_mod_value.sh 10003 state Approved" exit 0 # 将return替换为exit fi
4. 其他优化建议
- 给临时文件加上唯一标识(比如
tmp.$$),避免和其他脚本的临时文件冲突 - 添加命令执行结果检查,比如判断
accurev xml是否成功,避免后续处理空文件 - 变量引用尽量加上双引号(比如
"$currentFile"),防止文件名含空格时出现异常
修复后的完整脚本
#!/bin/bash issueNum=$1 field=$2 newValue=$3 typeset -A fidMap # fidMap['type']=7 #fidMap['customerName']=63 #fidMap['patchNum']=58 #fidMap['releaseImplmntdIn']=42 fidMap['state']=5 #fidMap['subsystem']=13 #fidMap['changeRequestNumber']=36 #fidMap['releaseFoundIn']=39 #fidMap['System']=35 #fidMap['assignedTo']=14 if [ "$1" = "" ] || [ "$2" = "" ] || [ "$3" = "" ]; then echo "Please pass in three variables: issueNumber field value" echo "Example: new_mod_value.sh 10003 state Approved" exit 0 fi echo "issue number $issueNum" echo "field is $2" echo "value is $3" rm -f runIssue.xml issuesOutputtmp.xml echo "<queryIssue issueDB=\"TEOCO\" expandUsers=\"true\">" > runIssue.xml echo "1 == $issueNum" >> runIssue.xml echo "</queryIssue>" >> runIssue.xml # 检查accurev查询是否成功 if ! accurev xml -l runIssue.xml > issuesOutputtmp.xml; then echo "Error running accurev xml query" exit 1 fi currentFile=issuesOutputtmp.xml # 使用sed -i原地修改,避免临时文件mv操作 sed -i.bak 's/<issues>/<modifyIssue issueDB="TEOCO">/' "$currentFile" && rm "${currentFile}.bak" sed -i.bak 's/<\/issues>/<\/modifyIssue>/' "$currentFile" && rm "${currentFile}.bak" sed -i.bak 's/fid="2">[0-9]*<\/transNum>/fid="2"><\/transNum>/' "$currentFile" && rm "${currentFile}.bak" grep "<$field" "$currentFile" >/dev/null if [ $? -eq 0 ]; then sed -i.bak "s/fid=\"${fidMap[$field]}\">.*/fid=\"${fidMap[$field]}\">$newValue<\/$field>/" "$currentFile" rm "${currentFile}.bak" else sed -i.bak "s/<\/issue>/<$field fid=\"${fidMap[$field]}\">$newValue<\/$field> <\/issue>/" "$currentFile" rm "${currentFile}.bak" fi # 转义处理 sed -i.bak 's/&/,/g' "$currentFile" && rm "${currentFile}.bak" #sed -i.bak 's/</\</g' "$currentFile" && rm "${currentFile}.bak" #sed -i.bak 's/>/\>/g' "$currentFile" && rm "${currentFile}.bak" #sed -i.bak 's/"/\"/g' "$currentFile" && rm "${currentFile}.bak" #sed -i.bak 's/[^!-~\s]//g' "$currentFile" && rm "${currentFile}.bak" accurev xml -l "$currentFile"
这样修改后,不仅解决了mv: cannot stat 'tmp'的错误,还让脚本更健壮、更易维护。
内容的提问来源于stack exchange,提问作者Stacker
相关产品推荐
相关产品推荐

