Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Feb 2000 08:53:58 +0100 (CET)
From:      Oliver Fromme <olli@dorifer.heim3.tu-clausthal.de>
To:        freebsd-questions@FreeBSD.ORG
Subject:   Re: OFF TOPIC - Shell Script Question
Message-ID:  <200002090753.IAA48007@dorifer.heim3.tu-clausthal.de>
In-Reply-To: <87q4gd$1gv1$1@atlantis.rz.tu-clausthal.de>

next in thread | previous in thread | raw e-mail | index | archive | help
Mark Ovens <mark@dogma.freebsd-uk.eu.org> wrote in list.freebsd-questions:
 > On Tue, Feb 08, 2000 at 02:34:25PM -0600, Darryl Hoar wrote:
 >> I have a directory with a ton of files in it.  I need to move some of
 >> them to another
 >> directory.  Here's what I'm thinking:
 >> 
 >> ls -tl | grep '1999' | awk '{print "mv " $9 " /home/darryl/test"}'
 >> 
 >> but it does not 'execute' the mv command.  How do I get this cooking ?
 > 
 > 	$ for i in `ls -lt | grep 1999 | awk '{print $9}'`

Bad idea.  If it's a "ton of files", it might overflow the
maximum command line length.  Darryl's first approach was
better.

To actually execute the commands (instead of just printing them
to stdout, the output of the awk stage could pe simply piped
into sh.  Note that you can also integrate the grep as an awk
pattern, saving a process and some overhead.  Thus:

ls -l | awk '/1999/{print "mv " $9 " /home/darryl/test"}' | sh

Note, however, that there are a few possible problems.
First, you probably want to match "1999" against the date of
the file, but if the file is younger than 6 months, "ls -l"
does not print the year.  Use "ls -Tl" to always get a full
time stamp output -- then $9 is the year (4 digits), and $10
is the file name.

Second, the grep (and the awk pattern) match against the whole
line.  So if (for example) the size happens to contain the
digits "1999", it matches, too -- this is probably not desired.
Therefore it's better to check _only_ the column which contains
the year numbers:

ls -Tl | awk '($9==1999){print "mv " $10 " /home/darryl/test"}' | sh

Finally, the above will break if a filename happens to contain
special characters, such as spaces and quotes.  This is more
difficult to work around, but probably not worth the effort if
you can avoid such filenames.

By the way (off topic):  Actually this job of moving files
would be a very typical use of the xargs command, which is more
efficient, but the problem is that the "mv" command expects the
destination directory as the last argument.  Therefore, I wrote
a small shell script for myself, which takes the destination
directory as the _first_ argument, and then a number of files
to move:

#!/bin/sh -
DEST="$1"; shift; exec /bin/mv "$@" "$DEST"

Calling that script "vm" (rev of "mv"), the problem could be
solved like this:

ls -Tl | awk '($9==1999){print $10}' | xargs vm /home/darryl/test

The big advantage of this, of course, is that the mv command
will be called for multiple files at once, while the first
solution exec's a mv command for every single file to move,
which is terribly inefficient, especially if there are a ton
of them...  (For the same reason, the -exec primary of the
"find" command is evil and should not be used in general --
use xargs instead.)

Regards
   Oliver

-- 
Oliver Fromme, Leibnizstr. 18/61, 38678 Clausthal, Germany
(Info: finger userinfo:olli@dorifer.heim3.tu-clausthal.de)

"In jedem Stück Kohle wartet ein Diamant auf seine Geburt"
                                         (Terry Pratchett)


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200002090753.IAA48007>