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

Help: file delete does not work on multiple files

2,479 views
Skip to first unread message

Hai Vu

unread,
Aug 22, 2008, 1:40:58 PM8/22/08
to
I have a directory called 'logs' which houses *.txt. At the start of
my script, I would like to delete all of these files to start from a
clean slate, so I put these lines in my script:

file delete logs/*.txt

which does delete any file at all. Next, I tried:

file delete [glob -nocomplain logs/*.txt]

and it did not work, either. I have verified that glob returned the
correct list. Finally, this works:

foreach logFile [glob -nocomplain logs/*.txt] {file delete $logFile}

If you have any insight into why the first two approaches does not
work, I would like to hear from you. Thanks.
Hai

Gerry Snyder

unread,
Aug 22, 2008, 1:57:23 PM8/22/08
to
Hai Vu wrote:
> I have a directory called 'logs' which houses *.txt. At the start of
> my script, I would like to delete all of these files to start from a
> clean slate, so I put these lines in my script:
>
> file delete logs/*.txt
>
> which does delete any file at all. Next, I tried:
>
> file delete [glob -nocomplain logs/*.txt]

Did you try:

file delete {*}[glob -nocomplain logs/*.txt]

? (if using 8.5)


HTH,


Gerry

Bruce

unread,
Aug 22, 2008, 2:07:50 PM8/22/08
to
Hai Vu wrote:
> I have a directory called 'logs' which houses *.txt. At the start of
> my script, I would like to delete all of these files to start from a
> clean slate, so I put these lines in my script:
>
> file delete logs/*.txt
>
> which does delete any file at all. Next, I tried:

because there is no file named "*.txt" no magic expansion is
done by the file command - it expects a filename

>
> file delete [glob -nocomplain logs/*.txt]
>
> and it did not work, either. I have verified that glob returned the
> correct list.

good, you found the glob command to handle the expansion, but now
you have another mistake. as you noted - glob reurns a list. the
file delete command does *not* expect a list, but treats each
argument as a singfle filename - so it was trying to delete
a file like "logs/1.txt logs/2.txt logs/3.txt" which doesn't
exist. if a simple case where glob returned 1 file it would have
luckily worked.

> correct list. Finally, this works:
>
> foreach logFile [glob -nocomplain logs/*.txt] {file delete $logFile}
>
> If you have any insight into why the first two approaches does not
> work, I would like to hear from you. Thanks.
> Hai

this deletes each file one at a time which indeed works, but file delete
does accept multiple arguments so you can do it in one call - you just
need to get data from a list into separate arguments, because the
interpreter (see main Tcl man page) does not change word boundaries
when perform variable or command substitution. so the default


file delete [glob -nocomplain logs/*.txt]

the main parser sees 3 "words" and on is the [..] subcommand which
is then run and the results substituted into the file delete command
as a single arg. so you need a way to break apart the list. If you
are using Tcl version 8.5 there is an expansion operator that does just
that - tells the interpreter to splitup the list into individual words
sent to the command, so


file delete {*}[glob -nocomplain logs/*.txt]

should work for you. if you are on 8.4 or earlier you will need to
use eval to cause an extra round of substitution which will accomplish
the same thing
eval file delete [glob -nocomplain logs/*.txt]


Hope it helps,
Bruce

Hai Vu

unread,
Aug 22, 2008, 2:25:16 PM8/22/08
to
Thank you Gerry and Bruce for your solutions. My system at work is
still at 8.4, so I cannot try the expansion solution, but eval works.
Here is another solution, which I adapted: delete the whole logs
directory, then recreate it. This solution works since I notice that
the logs directory contains only *.txt file and nothing else:

file delete -force logs
file mkdir logs

Ron Fox

unread,
Aug 22, 2008, 3:37:14 PM8/22/08
to

Because it's doing what it's documented to do:

file delete ?-force? ?- -? pathname ?pathname ... ?
Removes the file or directory specified by each pathname argument.
Non-empty directories will be removed only if the -force option is
specified. When operating on symbolic links, the links themselves will
be deleted, not the objects they point to. Trying to delete a
non-existent file is not considered an error. Trying to delete a
read-only file will cause the file to be deleted, even if the -force
flags is not specified. If the -force option is specified on a
directory, Tcl will attempt both to change permissions and move the
current directory 'pwd' out of the given path if that is necessary to
allow the deletion to proceed. Arguments are processed in the order
specified, halting at the first error, if any. A - - marks the end of
switches; the argument following the - - will be treated as a pathname
even if it starts with a -.


As others have said you can use eval to 'flatten' the list glob
returns into individual arguments to file delete
eval {file delete [glob -nocomplain logs/*.txt]}

But you should probably catch that as the case when the glob returns
an empty list is problematic file delete

--
Ron Fox
NSCL
Michigan State University
East Lansing, MI 48824-1321

pad...@gmail.com

unread,
Jan 15, 2015, 2:01:39 PM1/15/15
to
Sheez! Is it really so difficult to delete a few files?

Rich

unread,
Jan 15, 2015, 5:26:57 PM1/15/15
to
pad...@gmail.com wrote:
> Sheez! Is it really so difficult to delete a few files?

Code please. How are you calling file delete? Please copy/paste the
exact code if you would.

heinrichmartin

unread,
Jan 23, 2015, 4:24:42 AM1/23/15
to
> eval {file delete [glob -nocomplain logs/*.txt]}

no braces here:

expect:~$ proc echo args {foreach arg $args {puts $arg}}
expect:~$ eval {echo [list "a b" c]} ;# 1 == [llength $args] in echo!
{a b} c
expect:~$ eval echo [list "a b" c] ;# Tcl < 8.5
a b
c
expect:~$ echo {*}[list "a b" c] ;# Tcl >= 8.5
a b
c
expect:~$

heinrichmartin

unread,
Jan 23, 2015, 4:27:25 AM1/23/15
to
> expect:~$ proc echo args {foreach arg $args {puts $arg}}

even better: proc echo args {info level 0}

Andreas Kupries

unread,
Feb 20, 2015, 3:08:10 AM2/20/15
to
heinrichmartin <martin....@frequentis.com> writes:

>> eval {file delete [glob -nocomplain logs/*.txt]}

package require Tcl 8.5
file delete {*}[glob -nocomplain logs/*.txt]

On {*}, see http://wiki.tcl.tk/17158

--
So long,
Andreas Kupries <akup...@shaw.ca>
<http://www.purl.org/NET/akupries/>
Developer @ <http://www.activestate.com/>

EuroTcl 2015, June 20-21, Colgne/DE, http://www.eurotcl.tcl3d.org/
22'nd Tcl/Tk Conference: Manassas, VA, USA
-------------------------------------------------------------------------------

Don Porter

unread,
Feb 20, 2015, 9:13:02 AM2/20/15
to
On 02/20/2015 02:32 AM, Andreas Kupries wrote:
> heinrichmartin <martin....@frequentis.com> writes:
>
>>> eval {file delete [glob -nocomplain logs/*.txt]}
>
> package require Tcl 8.5
> file delete {*}[glob -nocomplain logs/*.txt]
>
> On {*}, see http://wiki.tcl.tk/17158
>

You'll need [package require Tcl 8.6] for that.

Otherwise, [file delete] will not be happy to get 0 arguments.

--
| Don Porter Applied and Computational Mathematics Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
0 new messages