Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tcl script hangs on deleting directory from remote machine while works for files

233 views
Skip to first unread message

sunny

unread,
May 27, 2011, 12:25:32 AM5/27/11
to
Hi All,

As a part of my tcl script, my requirement is i need to delete
contents (i.e. files and directories with my login id) from remote
machine. So i am using following code

catch {exec /usr/bin/rsh $mac_n {\rm -r ls -lrt /local/test | grep
$username | awk {{ print $NF}}}} err1

Now this code deletes files successfully and instantaneously but it
hangs while deleting folders.

I also tried an alternative solution for deleting files of my login
using csh script, but again while executing same script from tcl it
hangs.

Can some one please help me in figuring out the problem with this
code.

Donal K. Fellows

unread,
May 27, 2011, 4:50:43 AM5/27/11
to
On May 27, 5:25 am, sunny <techbie.wordpr...@gmail.com> wrote:
> As a part of my tcl script, my requirement is i need to delete
> contents (i.e. files and directories with my login id) from remote
> machine. So i am using following code
>
> catch {exec  /usr/bin/rsh $mac_n {\rm -r ls -lrt /local/test | grep
> $username | awk {{ print $NF}}}} err1

I find it hard to believe that that's exactly what you use given that
you say it works for some things; I suspect it got mangled during
posting. (That sort of thing happens.) We need to see exactly what is
being used (well, not including any passwords) in order to diagnose
problems.

It would also help if you described exactly what results (independent
of the side-effect of deleting stuff) you expect to get out of it.

Donal.

sunny

unread,
May 27, 2011, 4:48:14 AM5/27/11
to
I have found another solution for deleting files using output from
grep as:

exec ls -ltr | grep userid | awk {{print $NF}} | xargs rm -r

Now this code is working only on running this on that particular
machine. If i want to run this code from a remote machine, this is
still not working.

I have lot of machines (linux, solaris and ibm machines) where i need
to perform this operation as i can't do this operation manually. I
want to do this operation form tcl script only.

Now for deleting data from remote machine, i am using following code:

exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
$userid | awk {{print $NF}} | xargs rm -rx}"

Now this is reporting error : undefined variable NF.

So if i do it like :

exec /usr/bin/rsh machine_name {(cd /local/test; ls -ltr | grep
$userid | awk {{print $NF}} | xargs rm -rx}}

Then it is reporting error as : Missing }

I am not able to figure out a solution for this problem, appreciate if
some one can help me to get out of this problem.

Donal K. Fellows

unread,
May 27, 2011, 5:06:12 AM5/27/11
to
On May 27, 9:48 am, sunny <techbie.wordpr...@gmail.com> wrote:
> Now for deleting data from remote machine, i am using following code:
>
> exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
> $userid | awk {{print $NF}} | xargs rm -rx}"
>
> Now this is reporting error : undefined variable NF.

Because you're mixing up between Tcl syntax and Shell syntax and AWK
syntax. It's a mess!

> So if i do it like :
>
> exec /usr/bin/rsh machine_name {(cd /local/test; ls -ltr | grep
> $userid | awk {{print $NF}} | xargs rm -rx}}
>
> Then it is reporting error as : Missing }

Still all mixed up.

> I am not able to figure out a solution for this problem, appreciate if
> some one can help me to get out of this problem.

The best way to fix your problem is to do it a different way. The
'find' utility is excellent for this sort of thing:

exec /usr/bin/rsh $host "find /local/test -user $userid -delete"

I'm putting the string to execute remotely in double-quotes because I
want the user id to be substituted _locally_ and I'm assuming it has
no evil characters in it (that's a pretty safe assumption for user
names!)

Note: it doesn't need ls, or grep, or awk. (It could have been written
with xargs, but there's good reasons to not do that when deleting
directory hierarchies.)

Donal.

Alexandre Ferrieux

unread,
May 27, 2011, 5:15:45 AM5/27/11
to
On 27 mai, 11:06, "Donal K. Fellows"

<donal.k.fell...@manchester.ac.uk> wrote:
>
> The best way to fix your problem is to do it a different way. The
> 'find' utility is excellent for this sort of thing:
>
>   exec /usr/bin/rsh $host "find /local/test -user $userid -delete"
>
> I'm putting the string to execute remotely in double-quotes because I
> want the user id to be substituted _locally_ and I'm assuming it has
> no evil characters in it (that's a pretty safe assumption for user
> names!)

Beware that the -delete flag is a rather recent addition in 'find''s
life (eg absent on RHEL4).
An older syntax that works across the board:

exec /usr/bin/rsh $host "find /local/test -user $userid -exec rm \\
{\\} \\;"

The backslashes are doubled for Tcl substitution (passing them as
singles), and then the resulting \{\} and \; are two shell-escaped
arguments to 'find'.

-Alex

sunny

unread,
May 27, 2011, 6:32:35 AM5/27/11
to
Many thanks to both Donal & Alex for providing solution.

Finally it worked with:

exec /usr/bin/rsh $host "cd /local/test; find . -user $userid -exec rm
\\{\\} \\;"

Now one question still remains, why this was not working with the
following code:

exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
$userid | awk {{print $NF}} | xargs rm -rx}"

I have read some where on net that for awk to work with tcl, you
should use '{' instead of '. Now if i execute same code by logging
into machine manually from tcl shell, it works absolutely fine.

exec ls -ltr | grep userid | awk {{print $NF}} | xargs rm -r

To resolve this , i had used

exec /usr/bin/rsh machine_name {(cd /local/test; ls -ltr | grep
$userid | awk {{print $NF}} | xargs rm -rx}}

But it was not substituting variables, and hence was getting error.

Any idea on how to make it work through awk code as well.

I am running script from Linux 5 Machine and remote logging to ibm
machine.

Alexandre Ferrieux

unread,
May 27, 2011, 9:20:13 AM5/27/11
to
On 27 mai, 12:32, sunny <techbie.wordpr...@gmail.com> wrote:
> Many thanks to both Donal & Alex for providing solution.
>
> Finally it worked with:
>
> exec /usr/bin/rsh $host "cd /local/test; find . -user $userid -exec rm
> \\{\\} \\;"
>
> Now one question still remains, why this was not working with the
> following code:
>
> exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
> $userid | awk {{print $NF}} | xargs rm -rx}"


Because (1) you're trying to use 'Tcl braces' in a place where Tcl's
teeth cannot chew :P, and (2) you failed to protect a dollar.

Indeed, in the above, "(cd /local/test; ls -ltr | grep $userid | awk
{{print $NF}} | xargs rm -rx}" is a single string passed as the 3rd
argument to [exec].
Following Tcl's rules with double quotes, normal dollar+backslash
+bracket expansion occurs. You do want it to dollar-expand $userid,
but you don't for $NF (because you want awk to see the dollar). That's
error (1), fix it by saying \$NF.

Then, none of the braces receives any special attention from Tcl's
toplevel-double-quotes processing, so they go through untouched, down
to the shell (spawned by rsh remotely), to which a curly brace has a
completely unwanted meaning. That's error (2), fixed by using single
quotes.

So the final fixed code should be:

exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
$userid | awk '{print \$NF}' | xargs rm -rx}"

> I have read some where on net that for awk to work with tcl, you
> should use '{' instead of '.

That's the kind of sentence that, taken out of context, does more harm
than good.
The truth of the matter is simply to think carefully about which
programs reads which character at each level.
When Tcl is behind the wheel, give it {} to protect no-expansion
strings. When it's the shell, give it '. Awk has its own rules just
like any other program, and is no exception to the two ones just
listed:

exec awk {{print $1}}
exec sh -c {awk '{print $1}'}
exec sh -c "awk '{print \$1}'"
exec sh -c {awk "{print \$1}"}

all end up printing column 1. Look at them in detail to understand
why. After that you'll never hesitate again :)

-Alex

Ralf Fassel

unread,
May 27, 2011, 9:53:51 AM5/27/11
to
* Alexandre Ferrieux <alexandre...@gmail.com>

| So the final fixed code should be:
>
| exec /usr/bin/rsh machine_name "(cd /local/test; ls -ltr | grep
| $userid | awk '{print \$NF}' | xargs rm -rx}"

Note that there still is a paren mismatch (the remote command starts
with "(" and ends with "}") -- most probably a left-over from previous
try-and-error by the OP...

R'

Alexandre Ferrieux

unread,
May 27, 2011, 10:18:56 AM5/27/11
to
On 27 mai, 15:53, Ralf Fassel <ralf...@gmx.de> wrote:
> * Alexandre Ferrieux <alexandre.ferri...@gmail.com>

Good catch :)

To the OP: so the final fixed code should be:

exec /usr/bin/rsh machine_name "cd /local/test; ls -ltr | grep


$userid | awk '{print \$NF}' | xargs rm -rx"

-Alex

Glenn Jackman

unread,
May 31, 2011, 2:44:54 PM5/31/11
to

And it will still fail for any file with whitespace in it.

--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous

0 new messages