Date: Tue, 16 Jun 2009 14:05:10 -0400 (EDT) From: vogelke+unix@pobox.com (Karl Vogel) To: freebsd-questions@freebsd.org Subject: Re: Problem with bash script Message-ID: <20090616180510.7FCB1BEE4@kev.msw.wpafb.af.mil> In-Reply-To: <20090616151626.GD93430@torus.slightlystrange.org> (danielby@slightlystrange.org)
next in thread | previous in thread | raw e-mail | index | archive | help
>> On Tuesday, June 16, 2009 08:09:09 -0500 Carmel NY >> <carmel_ny@hotmail.com> wrote: C> I am attempting to write a simple Bash script that will find all the C> '*.pem' files in a directory structure and move them to another C> directory. Using find and pax will correctly handle filenames with spaces and other crap. If you use the -depth option in find, you'll also preserve directory modtimes: root# cd /src/directory root# mkdir -p /dest/directory root# find . -depth -print | pax -rwd -pe /dest/directory Use "-rwdu" if /dest/directory already exists and you don't want to overwrite newer files there with older files from /src/directory. If you want to store the output from pax as an archive file, use the "cpio" format for the most portability and the least number of limitations on things like pathname size. Another advantage of find vs backquotes is the ability to filter things out of the files being copied: root# find . -depth -print | fgrep -f /files/to/ignore | pax -x cpio -wd | gzip -1c > /tmp/src.pax.gz [ archive the pax file, copy it to another system, etc. ] root# cd /dest/directory root# gunzip -c < src.pax.gz | pax -r -pe If you have spaces in your filenames and you still want to do some filtering before running xargs, use tr to change newlines to nulls: root# find . -depth -print | /some/filter/here | tr '\012' '\000' | xargs -0 /some/command >> On Tue, 16 Jun 2009 16:16:26 +0100, >> "Daniel Bye" <danielby@slightlystrange.org> said: D> It does exactly the same as `command -a rgs`, but all characters between D> the parentheses are taken literally (in the backtick form, certain chars D> have special meaning, but not in the $() form.) Either solution will run the command first and then rescan the line in the calling script. You can run into problems when the results of the backquoted command are too big; there's an upper limit to how many arguments you can put in a for loop or pass to a program. Also, any spaces or weird characters in the output are likely to play hell with whatever else you're doing. You're much safer using a pipe. Use backquotes or $() when you're pretty sure the output won't be too big. To be safe, check the argument count when you run something: #!/bin/bash set X `date` # should give 6 tokens plus X. case "$#" in 1) echo "command didn't print anything" ;; 7) echo "success: $*"; echo "year should be 7th arg: $7" ;; *) echo "something else is wrong" ;; esac exit 0 -- Karl Vogel I don't speak for the USAF or my company There is nothing more satisfying than having someone take a shot at you and miss. --Murphy's Laws of Combat
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090616180510.7FCB1BEE4>