Unix Shell - exec script in all subdirs; pathnames contain spaces

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > February 2007 > exec script in all subdirs; pathnames contain spaces





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author exec script in all subdirs; pathnames contain spaces
Charles Russell

2007-02-21, 1:18 pm

I would like a bourne shell script (call it "global"), or a syntax for
the find command, that will execute an arbitrary script once each in the
current directory and all subdirectories. That is, $global script_X
should cd to each directory in the tree and then execute script_X. Not
hard with traditional unix pathnames, but I can't find the right quoting
or other tricks to make it work when there are spaces in the pathnames.
Stephane CHAZELAS

2007-02-21, 7:16 pm

2007-02-21, 13:12(-06), Charles Russell:
> I would like a bourne shell script (call it "global"), or a syntax for
> the find command, that will execute an arbitrary script once each in the
> current directory and all subdirectories. That is, $global script_X
> should cd to each directory in the tree and then execute script_X. Not
> hard with traditional unix pathnames, but I can't find the right quoting
> or other tricks to make it work when there are spaces in the pathnames.


#! /path/to/posix/sh -
# usage: global cmd arg arg
# (arg may not be ";").

find . -exec sh -c '
unset CDPATH
cd -P "$1" && shift && exec "$@"' inline {} "$@" \;

--
Stéphane
Stephane CHAZELAS

2007-02-21, 7:16 pm

2007-02-21, 19:20(+00), Stephane CHAZELAS:
> 2007-02-21, 13:12(-06), Charles Russell:
>
> #! /path/to/posix/sh -
> # usage: global cmd arg arg
> # (arg may not be ";").
>
> find . -exec sh -c '
> unset CDPATH
> cd -P "$1" && shift && exec "$@"' inline {} "$@" \;


Sorry, that was not a Bourne shell script. But do you really
need a Bourne shell script? The Bourne shell was common 15 years
ago, but not so much today, and it's not standard as per the new
Unix.

--
Stéphane
Charles Russell

2007-02-21, 7:16 pm

Stephane CHAZELAS wrote:
> 2007-02-21, 19:20(+00), Stephane CHAZELAS:
>
>
>
> Sorry, that was not a Bourne shell script. But do you really
> need a Bourne shell script? The Bourne shell was common 15 years
> ago, but not so much today, and it's not standard as per the new
> Unix.


Close enough. It runs on cygwin's ash shell, which is what I normally
use for scripts. The main idea was to be as portable as possible.

I haven't the foggiest notion how your script works, though. Could you
give me some clues where to look for documentation on "inline"? I can't
find it in ash, bash, or find. And what does the final "-" do on line 1
(starting with #!)?
Charles Russell

2007-02-21, 7:16 pm

Michael Tosch wrote:
> Charles Russell wrote:
>
>
>
> cat global
> #!/bin/sh
> find . -exec "$@" {} \;
>
> Try it with
> ./global ls -ld
> or
> ./global echo
>
>


Doesn't work in general. Needs -type d to return only files, not
directories, but still won't work; the directory names are returned
unquoted. The intent is to call the command within each subdirectory.
(My gl1 = your global)

$ ls
../ ../ gl1.sh* globl.sh* spl it/ spl it2/

$ gl1.sh pwd
pwd: ignoring non-option arguments
/home/cdr/junk
pwd: ignoring non-option arguments
/home/cdr/junk
pwd: ignoring non-option arguments
/home/cdr/junk
pwd: ignoring non-option arguments
/home/cdr/junk
pwd: ignoring non-option arguments
/home/cdr/junk
pwd: ignoring non-option arguments
/home/cdr/junk
Chris F.A. Johnson

2007-02-22, 1:24 am

On 2007-02-21, Charles Russell wrote:
> Michael Tosch wrote:
>
> Doesn't work in general. Needs -type d to return only files, not
> directories,


You have that backwards: Needs -type d to return only directories,
not files,

> but still won't work; the directory names are returned
> unquoted.


{} is the equivalent of a quoted pathname.

> The intent is to call the command within each subdirectory.
> (My gl1 = your global)
>
> $ ls
> ./ ../ gl1.sh* globl.sh* spl it/ spl it2/
>
> $ gl1.sh pwd


That doesn't work because pwd doesn't take any non-option
arguments, and the script executes the command with each filepath
as an argument.

Also, since you do not cd into the directory in question, pwd
always executes in the original directory.

> pwd: ignoring non-option arguments
> /home/cdr/junk
> pwd: ignoring non-option arguments
> /home/cdr/junk
> pwd: ignoring non-option arguments
> /home/cdr/junk
> pwd: ignoring non-option arguments
> /home/cdr/junk
> pwd: ignoring non-option arguments
> /home/cdr/junk
> pwd: ignoring non-option arguments
> /home/cdr/junk



--
Chris F.A. Johnson, author <http://cfaj.freeshell.org/shell>
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
===== My code in this post, if any, assumes the POSIX locale
===== and is released under the GNU General Public Licence
Charles Russell

2007-02-22, 1:24 am

Chris F.A. Johnson wrote:
> On 2007-02-21, Charles Russell wrote:
>
>
>
> You have that backwards: Needs -type d to return only directories,
> not files,
>
>
>
>
> {} is the equivalent of a quoted pathname.
>
>
>
>
> That doesn't work because pwd doesn't take any non-option
> arguments, and the script executes the command with each filepath
> as an argument.
>
> Also, since you do not cd into the directory in question, pwd
> always executes in the original directory.


Exactly. Perhaps my original posting was not clear enough, but the
objective is to cd into each subdirectory (with spaces in the pathname)
and from that location execute a specified script. Here I have
substituted the command "pwd" for the arbitrary script in order to show
that the objective is not met. Two methods that do seem to work have
been posted by Stephane Chazelas in this thread, and by Dan Mercer in
the adjacent thread "find -print0 confusing me".
Stephane CHAZELAS

2007-02-22, 7:19 am

2007-02-21, 15:55(-06), Charles Russell:
[...]
>
> Close enough. It runs on cygwin's ash shell, which is what I normally
> use for scripts. The main idea was to be as portable as possible.
>
> I haven't the foggiest notion how your script works, though. Could you
> give me some clues where to look for documentation on "inline"? I can't
> find it in ash, bash, or find. And what does the final "-" do on line 1
> (starting with #!)?


Inline is a "dummy" parameter. You can use anything there.

That parameter will become the inline-script's (the argument to
-c) $0 in POSIX shells.

find . -exec sh -c '
unset CDPATH
cd -P "$0" && exec "$@"' {} "$@" \;

would have been even simpler. It's just that $0 usually contains
the script name, so for inline scripts, I tend to use "inline".

--
Stéphane
Michael Tosch

2007-02-22, 7:19 am

Charles Russell wrote:
> Michael Tosch wrote:
>
> Doesn't work in general. Needs -type d to return only files, not
> directories, but still won't work; the directory names are returned
> unquoted. The intent is to call the command within each subdirectory.
> (My gl1 = your global)
>


cat global
#!/bin/sh
find . -type d -exec "$@" {} \;

You better do the cd in script_X:

cat script_X
#!/bin/sh
cd "$1"
pwd
....

global script_X


--
Michael Tosch @ hp : com
Charles Russell

2007-02-22, 1:18 pm

Michael Tosch wrote:
> You better do the cd in script_X:


Handier to have a generic tool that works with any script. That
conforms to the original unix principle of single-function tools that
work well in combination.

I'm just trying to rewrite my old tools to work with Windows pathnames.
My first "global", which I found very handy, was a utility for MS-DOS.
Then I wrote a simple equivalent shell script, that served me well for
years until I tried to use it on a Windows directory tree. Spaces in
filenames are a creation of the devil.

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com