Re: How to disable cp error message in bash?
- From: Stephane CHAZELAS <stephane_chazelas@xxxxxxxx>
- Date: Fri, 18 Jul 2008 10:28:48 +0000 (UTC)
2008-07-17, 10:50(-07), PengYu.UT@xxxxxxxxx:
Hi,[...]
I tried the following command. I don't what bash to report the error
message when there is no *.sh files. Is there a way to do it?
~$ cp /bin/*.sh ./
cp: cannot stat `/bin/*.sh': No such file or directory
Note that it is not bash that reports that error message, but
cp, so as others already pointed out, you may want to redirect
cp's stderr do /dev/null but that means you'll miss other errors
by cp.
However, it is indeed the shell that is failing to find any file
ending in ".sh" in the /bin directory.
There is what can be considered as a misfeature in most shells
including bash in that when a pattern doesn't match any file,
the shell doesn't complain but instead passes the pattern
untouched to the command.
So here, as /bin/*.sh doesn't match, the shell is asking "cp" to
copy a file called "/bin/*.sh". And as that file doesn't exist,
cp reports a problem.
It's not too big a problem for the "cp" command and for this
pattern. But imagine for instance:
rm -- *.[hc]
If there is no .h nor .c file, but there is a file "named"
"*.[hc]", you'll end up removing a file you didn't want to
remove.
A few shells did fix that: csh and tcsh (to some extend) and
zsh.
In bash, you can fix it by doing a "shopt -s failglob"
In those shells, if you do:
cp /bin/*.sh .
If there is no file matching that pattern, then the *shell* will
report an error and not call "cp" which is a much more sensible
thing to do. You'll still get an error message though.
With bash (+failglob) or zsh, you can do:
{ files=(/bin/*.sh); } 2> /dev/null &&
cp -- "${files[@]}" .
This way, you don't get an error message if there's no .sh file,
but you still get to see the other "cp" errors.
With zsh, you could also do:
files=(/bin/*.sh(N))
(($#files)) && cp -- $files .
(N) makes so that if there is no matching file, the pattern
expands to nothing instead of reporting an error. Then
(($#files)) which returns false if the number of elements in the
$files array is 0 is a way to only run cp if there were .sh
files.
POSIXly, you could do:
set -- /bin/[*].sh /bin/*.sh
if [ "$1$2" != '/bin/[*].sh/bin/*.sh' ]; then
shift
cp -- "$@" .
fi
--
Stéphane
.
- Follow-Ups:
- References:
- How to disable cp error message in bash?
- From: PengYu.UT@xxxxxxxxx
- How to disable cp error message in bash?
- Prev by Date: Re: script help
- Next by Date: Re: How to disable cp error message in bash?
- Previous by thread: Re: How to disable cp error message in bash?
- Next by thread: Re: How to disable cp error message in bash?
- Index(es):
Relevant Pages
|