4
#! /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: robot@abc.com
rcpt to: asa@abc.com
data
subject: errors
$error_text
.
quit
EOF
mv Abc*.err /path/dir/folder/exc/a/update/Abd/ER/BkError/

The error I get is

mv: cannot stat `ACQ*.err': No such file or directory

2 Answers2

1

When invoking a program with a wildcard, then the shell you're using will try to expand this wildcard and give the expanded filenames as arguments to the executable. If it cannot be expanded, the shell gives the wildcards as filenames to the process.

See the following strace output (the files exist):

user@host:~$ mv test* /tmp/
execve("/bin/mv", ["mv", "test", "test1", "test2", "test3", "/tmp"], [/* 19 vars */]) = 0

Now, this strace output (no file matching the wildcard exists).

user@host:~$ mv test* /tmp/
execve("/bin/mv", ["mv", "test*", "/tmp/"], [/* 19 vars */]) = 0

When moving a file with mv, the program mv first tries to get the status of the file. That's been done with a syscall stat (see man 2 stat). If the status of the file (or multiple files in your case) cannot be gathered, the mv process cannot continue.

In the second case the stat syscall fails:

lstat("test*", 0x7fff20d26490)          = -1 ENOENT (No such file or directory)

To cut a long story short: No files exist that match the statement ACQ*.err.

slm
  • 369,824
chaos
  • 48,171
  • All of that is correct, but it doesn't explain why mv complains about ACQ*.err when the code snippet states mv Abc*.err, so it seems OP didn't post the actual code in question. – Adrian Frühwirth Jun 10 '14 at 08:13
  • @AdrianFrühwirth hm, that's true I overread that, but it's certainly a typo. – chaos Jun 10 '14 at 09:29
1

When a wildcard pattern doesn't match any file, the shell leaves it unchanged.

To avoid a spurious error, first let the matches be expanded, then check if the result is a non-existent file.¹ You can set the positional parameters (which normally contain the arguments passed to the script) to the list of files.²

set -- Abc*.err
if [ -e "$1" ]; then
  mv "$@" /path/dir/folder/exc/a/update/Abd/ER/BkError/
fi

In bash, but not in plain sh, you can change the configuration to expand non-matching patterns to the empty string instead of leaving them intact.

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

¹ This can lead to false positives with patterns containing […]. For completeness's sake, you should also test whether the expansion is equal to the original.
² See “How do I process a list of file names” in Why does my shell script choke on whitespace or other special characters? for more explanations.