Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

A command like mv foo* ~/bar/ produces this message in stderr if there are no files matching foo*.

mv: cannot stat `foo*': No such file or directory

However, in the script I'm working on that case would be completely fine, and I'd like to omit that message from our logs.

Is there any nice way to tell mv to be quiet even if nothing was moved?

share|improve this question
9  
mv foo* ~/bar/ 2> /dev/null ? –  Thomas Nyman Aug 21 '13 at 11:14
1  
Well yeah. I guess I had something "nicer" in mind, like some switch for mv. :) But that will do, of course. –  Jonik Aug 21 '13 at 11:34
3  
I've seen some mv implementations support a -q option to quiet them down, but that is not part of the POSIX specification for mv. The mv in GNU coreutils, for instance, does not have such an option. –  Thomas Nyman Aug 21 '13 at 11:53
    
Well, I dont think the problem is how to keep "mv" be quiet, but how to do it more properly. Checking if there is any file/dir foo*, and user has writable permission, finally execute "mv", perhaps? –  Shâu Shắc Aug 22 '13 at 7:00

8 Answers 8

Are you looking for this?

$ mv  file dir/
mv: cannot stat ‘file’: No such file or directory
$ mv  file dir/ 2>/dev/null
# <---- Silent ----->
share|improve this answer
2  
note, return value still != 0, therefore any set -e (which should be used in every shell script) will fail. you can add a || true to deactivate the check for a single command. –  reto Aug 21 '13 at 16:28
    
@reto set -e should not be used in every shell script, in many cases it makes error management even more complex than it is without. –  Chris Down Nov 4 '13 at 9:12
    
@ChrisDown I see your point. It is usually a choice between two evils. But if in doubt, I prefer a failed successful run, than a successful failure. (which doesn't get noticed until it's getting visible to a customer/user). Shell scripts are a big mine field for beginners, it's so easy to miss a an error and your script goes haywire! –  reto Nov 4 '13 at 10:25

Actually, I don't think muting mv is a good approach (remember it might report you also on other things which might be of interest ... eg. missing ~/bar). You want to mute it only in case your glob expression doesn't return results. In fact rather not execute it at all.

[ -n "$(shopt -s nullglob; echo foo*)" ] && mv foo* ~/bar/

Doesn't look very appealing, and works only in bash.

OR

[ 'foo*' = "$(echo foo*)" ] || mv foo* ~/bar/

only except you are in bash with nullglob set. You pay a price of 3x repetition of glob pattern though.

share|improve this answer

find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/

— GNU's mv has nice "destination first" option (-t) and xargs can skip running its command if there's no input at all (-r). Using of -print0 and -0 correspondingly makes sure there wouldn't be a mess when filenames contain spaces and other "funny" stuff.

share|improve this answer
    
Thanks, I was working on the answer but without the -t I would lose all the files except the last if ~/bar/ didn't exist. Replace your -print0 | ... with -exec mv -t ~/bar/ '{}' + and this is a great answer. –  drewbenn Aug 21 '13 at 17:02
    
Ough, possibly I should ask — why using find's -exec instead of xargs? –  poige Aug 21 '13 at 17:11
    
using -exec keeps everything within the find process, i.e. "it's more efficient." It's not required, just a little bit nicer. [[ I'd lose all but the last file with -exec mv '{}' ~/bar/ \;. Being able to use -exec mv -t ~/bar/ + instead solves that problem. ]] FYI you're missing the trailing quote on 'foo *', and -maxdepth 1 should come before -name. –  drewbenn Aug 21 '13 at 17:13
    
Well, I should be more careful what I say: stackoverflow.com/questions/896808/find-exec-cmd-vs-xargs . How about, -exec is better because I prefer it :) –  drewbenn Aug 21 '13 at 17:21
    
@drewbenn yep, thanks that noticed it, fixed now. –  poige Aug 22 '13 at 3:11

You can do for example

mv 1>/dev/null 2>&1 foo* ~/bar/ or mv foo* ~/bar/ 1&>2

For more details see: http://mywiki.wooledge.org/BashFAQ/055?highlight=%28which%29

share|improve this answer
    
mv foo* ~/bar/ 1&>2 does not silence the command, it sends what would have been on stdout to also be on stderr. –  Chris Down Aug 21 '13 at 12:15
    
@ChrisDown you are right, however this be noticed if you ran cp -rv foo* ~/bar/ Since mv in it's own is silent it won't matter at all. But then yes the second command is somehow not useful. Edit errors please :> –  val0x00ff Aug 21 '13 at 12:18

I'm assuming that you are using bash, because this error depends on bash's behavior to expand unmatched globs to themselves. (By comparison, zsh raises an error when trying to expand an unmatched glob.)

So, what about the following workaround?

ls foo* >/dev/null 2>&1 && mv foo* ~/bar/

This will silently ignore the mv if ls foo* fails, while still logging errors if ls foo* succeeds but the mv fails. (Beware, ls foo* could fail for other reasons than foo* not existing, e.g., insufficient rights, problem with the FS, etc., so such conditions would be silently ignored by this solution.)

share|improve this answer
    
I'm mostly interested in bash, yeah (and I did tag the question as bash). +1 for taking into account the fact that mv might fail for other reasons than foo* not existing. –  Jonik Aug 22 '13 at 12:27
    
(In practice I probably won't be using this since it's kind of verbose, and the point of the ls command wouldn't be very clear for future readers, at least without a comment.) –  Jonik Aug 22 '13 at 12:28

You can cheat (portably) with perl:

perl -e 'system "mv foo* ~/bar/" if glob "foo*"'
share|improve this answer
    
Please comment before downvoting. –  Joseph R. Aug 21 '13 at 18:40

If you're going to use Perl, you might as well go all the way:

#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;

my $target = "$ENV{HOME}/bar/";

foreach my $file (<foo*>) {
    move $file, $target  or warn "Error moving $file to $target: $!\n";
}

or as a one-liner:

perl -MFile::Copy -E 'move $_, "$ENV{HOME}/bar/" or warn "$_: $!\n" for <foo*>'

(For details of the move command, see the documentation for File::Copy.)

share|improve this answer

Instead

mv foo* ~/bar/

you can do

cp foo* ~/bar/
rm foo* 

Simple, readable, vote me :)

share|improve this answer
1  
Copying, then removing, takes longer than a simple move. It also will not work if a file is larger than the available free disc space. –  Anthon Apr 14 at 7:14
    
The OP wants a solution that is silent. Neither cp nor rm are silent if foo* does not exist. –  ron.rothman Oct 3 at 13:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.