#! /bin/bash
error_text=$(tail -n +1 /path/dir/folder/exc/a/update/Abd/ER/* | \
grep 'Warning\|Loaded\|Event')
echo $error_text
nc 10.10.99.45 25 << EOF
ehlo mail.abc.pvt
mail from: [email protected]
rcpt to: [email protected]
data
subject: errors
$error_text
.
quit
EOF
mv Abc*.err /path/dir/folder/exc/a/update/Abd/ER/BkError/
我得到的错误是
mv: cannot stat `ACQ*.err': No such file or directory
答案1
当使用通配符调用程序时,您使用的 shell 将尝试扩展此通配符并将扩展的文件名作为可执行文件的参数。如果无法扩展,shell 会将通配符作为文件名提供给进程。
查看以下strace
输出(文件存在):
user@host:~$ mv test* /tmp/
execve("/bin/mv", ["mv", "test", "test1", "test2", "test3", "/tmp"], [/* 19 vars */]) = 0
现在,此strace
输出(不存在与通配符匹配的文件)。
user@host:~$ mv test* /tmp/
execve("/bin/mv", ["mv", "test*", "/tmp/"], [/* 19 vars */]) = 0
当使用 移动文件时mv
,程序mv
首先尝试获取文件的状态。这是通过系统调用完成的stat
(请参阅 参考资料man 2 stat
)。如果无法收集文件(或您的情况下的多个文件)的状态,则该mv
过程无法继续。
在第二种情况下,stat 系统调用失败:
lstat("test*", 0x7fff20d26490) = -1 ENOENT (No such file or directory)
长话短说: 不存在与该语句匹配的文件ACQ*.err
。
答案2
当通配符模式与任何文件都不匹配时,shell 会保持其不变。
为了避免虚假错误,首先让匹配项展开,然后检查结果是否是不存在的文件。 ¹ 您可以将位置参数(通常包含传递给脚本的参数)设置为文件列表。 ²
set -- Abc*.err
if [ -e "$1" ]; then
mv "$@" /path/dir/folder/exc/a/update/Abd/ER/BkError/
fi
在 bash 中(但不是 plain )sh
,您可以更改配置以将不匹配的模式扩展为空字符串,而不是保持它们不变。
shopt -s nullglob
err_files=(Abc*.err)
if ((${#err_files[@]} != 0)); then
mv "${err_files[@]}" /path/dir/folder/exc/a/update/Abd/ER/BkError/
fi
1这可能会导致包含[…]
.为了完整起见,您还应该测试扩展是否等于原始值。
²请参阅“如何处理文件名列表”为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?以获得更多解释。