The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   UNIX - Newcomers (http://hintsforums.macworld.com/forumdisplay.php?f=15)
-   -   removing the contents of a directory (http://hintsforums.macworld.com/showthread.php?t=90404)

ganbustein 06-06-2008 07:58 PM

Quote:

Originally Posted by Hal Itosis (Post 474759)
I just noticed something interesting.
Both "..." and "..secret_stash" are visible in Finder!

That's bizarre!

As for dealing with -r and -i files... as man rm mentions, rm uses getopt() to parse its arguments, so the usual -- option works.
rm -rf -- * .[^.] .??*
Hmm.. without that, a file named -- might prevent an unpredictable subset of your files from being deleted.

Of course, prefixing with ./ works also on systems where rm does not look for --.

Back in the olden days when I was learning Unix, I seem to recall that ? would not match a period. My first attempt was
rm -rf * .? ..?* ...*
but ? doesn't work like that anymore (if it ever actually did). I just thought I'd mention that.

This thread seems to be accentuating that every program still has at least one bug, even if the program is a one-liner. Anyone but me remember IEFBR14? Of course you can google it, but do you remember it without looking it up? (I don't know if the fact that today is my 62nd birthday, and I've been programming since I was 19, makes that easier or harder to remember.)

Hal Itosis 06-07-2008 10:47 AM

Quote:

Originally Posted by ganbustein (Post 474789)
That's bizarre!

As for dealing with -r and -i files... as man rm mentions, rm uses getopt() to parse its arguments, so the usual -- option works.
rm -rf -- * .[^.] .??*
Hmm.. without that, a file named -- might prevent an unpredictable subset of your files from being deleted.

Oh yeah... I'd forgotten about "--"

--

I found we can also circumvent the "-i" effect by changing the order so that the
bare asterisk is not first. For example... using ls with the -f option (to force it
to list items in the order they were submitted):
Code:

$ ls -lanf * .[^.] .??*
342395 -rw-r--r--  1 501  501  0 Jun  6 13:18 bar
342388 -rw-r--r--  1 501  501  0 Jun  6 13:32 .*
342394 -rw-r--r--  1 501  501  0 Jun  6 13:24 .z
342389 -rw-r--r--  1 501  501  0 Jun  6 13:18 ...
342390 -rw-r--r--  1 501  501  0 Jun  6 13:23 ....
342391 -rw-r--r--  1 501  501  0 Jun  6 13:18 ..secret_stash
342392 -rw-r--r--  1 501  501  0 Jun  6 13:32 .\*
342393 -rw-r--r--  1 501  501  0 Jun  6 13:18 .dot

$ echo * .[^.] .??*
-i bar .* .z ... .... ..secret_stash .\* .dot

Since the early * picked up the "-i" first, ls saw it as an (inode) option.
So the -i file isn't shown.

Now, reordering...
Code:

$ echo .[^.] .??* *
.* .z ... .... ..secret_stash .\* .dot -i bar

$ ls -lanf  .[^.] .??* *
-rw-r--r--  1 501  501  0 Jun  6 13:32 .*
-rw-r--r--  1 501  501  0 Jun  6 13:24 .z
-rw-r--r--  1 501  501  0 Jun  6 13:18 ...
-rw-r--r--  1 501  501  0 Jun  6 13:23 ....
-rw-r--r--  1 501  501  0 Jun  6 13:18 ..secret_stash
-rw-r--r--  1 501  501  0 Jun  6 13:32 .\*
-rw-r--r--  1 501  501  0 Jun  6 13:18 .dot
-rw-r--r--  1 501  501  0 Jun  6 15:54 -i

-rw-r--r--  1 501  501  0 Jun  6 13:18 bar

(-f wasn't necessary; it merely helped to reflect the actual input, which echo also showed).

As can be seen, I've been playing around with some other weird filenames: .* and .\*

hayne 06-07-2008 11:13 AM

Quote:

Originally Posted by ganbustein (Post 474596)
I made it as short as possible.

I know you didn't mean it this way, but if we are going for short (not to mention easier to type), it'd be better to use the following to delete all files & folders in the current directory:

find . -delete

Code:

% echo "rm -rf * .[^.] .??*" | wc -c
      20

% echo "find . -delete" | wc -c
      15


Hal Itosis 06-07-2008 12:14 PM

That's weird... find . -delete
finds '.' but it doesn't delete '.'
How come (no error nothin')?

hayne 06-07-2008 04:12 PM

Quote:

Originally Posted by Hal Itosis (Post 474882)
That's weird... find . -delete
finds '.' but it doesn't delete '.'
How come (no error nothin')?

It's merely that 'delete' is smart enough to know that it wouldn't make sense to delete the current directory. So it makes an exception for '.' and '..' - here's the relevant part of the source code:
Code:

        if (strcmp(entry->fts_accpath, ".") == 0 ||
            strcmp(entry->fts_accpath, "..") == 0)
                return 1;


Hal Itosis 06-07-2008 05:00 PM

:D :D :D Thread Closed! :D :D :D

No Further Information Necessary!

^^^

Well, there's still something to be said for the pattern approach:
it can be done from *outside* the folder. (I've already added a
Bash function to implement it... so it needs to be rationalized).

rm -fr foo/{.[^.],.??*,*}

will clear foo's content, but folder foo survives.
;)

ganbustein 06-07-2008 09:31 PM

Quote:

Originally Posted by hayne (Post 474872)
I know you didn't mean it this way, but if we are going for short (not to mention easier to type), it'd be better to use the following to delete all files & folders in the current directory:

find . -delete

It's true that I didn't mean it that way, but your version is not only shorter and easier to remember/type/understand, it's also more robust.

Code:


mkdir foo
cd foo
ls -a
.      ..
for (( i=0; i < 10000; ++i )); do touch someverylongfilenameprefix.$i; done
# very long wait...
rm *
-bash: /bin/rm: Argument list too long
sysctl kern.argmax
kern.argmax = 262144
# Aha! 10000 filenames at 27+ characters each exceeds kern.argmax
find . -delete
# very short wait...
ls -a
.      ..

The difference is that rm * forces bash to expand the complete list of files before handing it to rm, and the list is too long for IPC to handle. With find, -delete deletes each item immediately. No list needs to be created. I yield to the superior solution.

Hal: here's a start on your function:
Code:

rmstar ()
{
    local oldpwd="$PWD";
    cd "${1:-$oldpwd}" && find . -delete;
    local result=$?;
    cd "$oldpwd";
    return $result
}

I found that I kept getting errors out of find when I tried find "$1" -delete or variations thereof. For one thing, while find . -delete won't find and delete '.', find foo -delete will happily find and delete 'foo'. Say what? And $1 might or might not have a trailing slash. And after that there are warnings about relative pathnames, at which point I threw in the towel and just did a cd.

Add whatever additional error-checking code you deem appropriate. A nice refinement might be to loop across "$@" instead of just using "$1". Or have it accept files as well as directories.

Or just ask yourself how often you're really going to need this. After all:
rm -rf someDirectory
mkdir someDirectory
will almost always be good enough.

Hal Itosis 06-08-2008 02:24 AM

Quote:

Originally Posted by ganbustein (Post 474941)
Or just ask yourself how often you're really going to need this. After all:
rm -rf someDirectory
mkdir someDirectory
will almost always be good enough.

[shhhh... we don't want folks to think this stuff can be that simple.] ;)

Just Fred 09-25-2008 11:34 PM

Can I ask to go on another tangent? :)

I would like to be able to remove all the thumbnail files iPhoto creates. In each "primary" folder hierarchy ~/Pictures/iPhoto\ Library/<year>/<month>/ there can be a "Thumbs" directory containing these thumbnail files. I've been trying to use a combination of 'find' (to find the "Thumbs" directory and 'xargs' to delete the contents of these folders, but I can't seem to get it to work. As usual, I'm sure I'm overlooking something quite simple...

TIA

acme.mail.order 09-25-2008 11:47 PM

This one is very aggressive, the Four Horsemen of `find` annihilating entire directory trees at a stroke:

find . -iname '*thumb*' -exec rm -rf {} \;

Only two horses:

find . -type d -name thumb -exec rm {}/*jpg \;

Just Fred 09-26-2008 08:49 AM

Quote:

Originally Posted by acme.mail.order (Post 495522)
This one is very aggressive, the Four Horsemen of `find` annihilating entire directory trees at a stroke:

find . -iname '*thumb*' -exec rm -rf {} \;

Only two horses:

find . -type d -name thumb -exec rm {}/*jpg \;

Hmmm, I thought I'd tried those combinations, without success. It looks like the second would do the trick. I'd change it to

find . -type d -name Thumbs -exec rm {}/*jpg \;

Simply to guard against the possibility (however unlikely) that there might be a folder with "thumb" somehow in its name.

Thanks!


All times are GMT -5. The time now is 10:13 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.