The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   UNIX - Newcomers (http://hintsforums.macworld.com/forumdisplay.php?f=15)
-   -   delete all files except.... (http://hintsforums.macworld.com/showthread.php?t=100084)

fracai 03-27-2009 09:42 AM

Are you sure it's not deleting anything? Or just not printing the result?

add -print before -delete and try it again.

kaptagat 03-27-2009 11:29 AM

No, none of the applications are being deleted.

The command appears to work perfectly but nothing gets deleted. If I add
-print before -delete, then this comes back :-

Camino.app/Contents/MacOS/components/talkback/Talkback.app
Camino.app
untitled folder/Camino.app/Contents/MacOS/components/talkback/Talkback.app
untitled folder/Camino.app

kaptagat 03-31-2009 11:10 AM

So no one can suggest a reason why the found applications are not deleted?

Thanks in Anticipation.

fracai 03-31-2009 11:35 AM

A permissions issue?

If you're running "find <path> <search options> -print -delete" and you're seeing the app paths printed out, those directories should be deleted, unless you don't have the proper permissions to delete them. Though in that case I'd expect to see an error.

hayne 03-31-2009 11:52 AM

I haven't looked into this, but does 'find's "-delete" work to delete non-empty directories?
I would have guessed not since 'rm' won't delete non-empty directories (without the "-r" flag).

Hal Itosis 03-31-2009 01:54 PM

Quote:

Originally Posted by kaptagat (Post 526060)
So using this : find * -name '*.app' -prune -print returns this:-
Camino.app
untitled folder/Camino.app

But when I run (as root) find * -name '*.app' -prune -delete
it doesn't delete anything.

Those two find commands (from post #20) are awkwardly written.

"find *" is neither conventional nor wise (imho).
Use a definite path (else, -f with more than one path).

And, "-prune" in the context of those two statements is going to do strange things.
[a few test runs show it skips apps which reside *inside* of other apps... weird.]

Anyway, i won't comment further until i see a proper search path and proper use of prune.
(in fact, -prune is probably not needed... unless you're trying to skip specific subregions).

--

i think hayne may be right about the behavior of -delete,
but the odd syntax above certainly doesn't help either.

EDIT: in fact, here is an interesting mix of conditions (from man find):
-d Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the default is not a breadth-first traversal.

-depth Always true; same as the -d option.

-delete Delete found files and/or directories. Always returns true. This executes from the current working directory as find recurses down the tree. It will not attempt to delete a filename with a ``/'' character in its pathname relative to ``.'' for security reasons. Depth-first traversal processing is implied by this option.

-prune This primary always evaluates to true. It causes find to not descend into the current file. Note, the -prune primary has no effect if the -d option was specified.

So... -delete implies -depth (-d), and -prune doesn't perform its intended function under that condition?

idunno, but it looks like hayne's suggestion that using rm -r is what's needed (either pipe to xargs or use -exec).

I'm highly hesitant to actually *post* any working "rm -r" solutions however! :D

kaptagat 04-01-2009 06:11 AM

Hal Itosis

Thanks for your reply but there is no path because, for safety's sake, I am testing the command within the "Student's Temporary Folder". I am well aware of the danger of rm -r and I have no wish to wreck my machine.

Following your tip, I have looked into using -exec with find, and have come up with :-

find * -name '*.app' -exec rm -r {} \;

This command finds all applications and deletes them.

Hal Itosis 04-01-2009 02:28 PM

Quote:

Originally Posted by kaptagat (Post 526830)
Thanks for your reply but there is no path because, for safety's sake, I am testing the command within the "Student's Temporary Folder".

In that case, the proper syntax is: find .

While a few test runs show that "find *" seems to work, i wouldn't trust it.
I have never (never!) seen "find *" used in any script or webpage anywhere.
[unfortunately, google doesn't search for such strings successfully.]

But, we can see what's happening very easily... using execution tracing.

First, run this command in Terminal:
set -x
# for a conspicuously-colored trace prompt, also run: PS4=$'\[\e[37;41m\]+\[\e[0m\] '

Now... go to various folders and compare what happens when running:
find . -name '*.app'
versus:
find * -name '*.app'

The results may be identical, but you can see that very *different* arguments are being fed to find.
[and -- because of all those unnecessary arguments -- you might encounter some pitfall one day.]

When satisfied, turn off tracing via:
set +x

kaptagat 07-10-2009 07:13 AM

Still working on this for a neat solution without using the find command which is a complete minefield to a beginner. I am looking to use the inverse function of grep to find everything in the shared folder which is not called Adobe or Infected and then delete them.

I have got as far as this :-

rm -r `ls | grep -v "Adobe" | grep -v "Infected"`

This runs the ls grep command and then the rm command. I thought I had cracked it but bizarrely it doesn't delete any folders or files that have spaces in their names.

For example, untitledfolder gets removed but untitled folder comes back with :-
rm: untitled: No such file or directory
rm: folder: No such file or directory

Anybody know why?

thanks

fracai 07-10-2009 10:55 AM

rm -r `blah` is dangerous. Partly for the bug you've seen. Because "untitled folder" contains a space, it is interpreted as 2 arguments. A better solution along these lines would use xargs to tokenize your arguments and kick off the rm command.

ls | grep -v "Adobe" | gre p-v "Infected" | gxargs -d "\n" rm -r

Will pipe the ouput of your ls and grep into xargs, splitting the result by new lines, and executing rm on each argument.
Note that I'm using gxargs. This is because the xargs provided by Apple does not support the -d argument. So I'm using gxargs as provided by MacPorts. An alternative would be to use find and -print0.

find . \! -name "*Adobe*" \! -name "*Infected*" -print0 | xargs -0 rm -r

In this case, -print0 prints records separated by ASCII 0 and -0 tells xargs to look for this token. \! tells find to invert the following match, so it should exclude files with Adobe or Infected in the name.

kaptagat 07-14-2009 06:40 AM

Thanks fraicai but macports is not on the machines so gxargs is a non starter and I cannot get xargs to work and I don't want to use the find command. (Your find command finds files inside the Adobe folder and deletes them which is not what I want.)

If I pipe the output of the ls and grep commands to a file, I will get a list of everything which must be deleted with each file or folder being on a separate line. Is there a way for the rm command to open a file and execute the contents line by line?

thanks

P.S. Tried xargs rm < file.txt but came up against the space problem again.

hayne 07-14-2009 08:28 AM

Look at the following - it should help you to figure out a solution to your problem:
Code:

% cat foo.txt
/MyStuff/my first file.txt
/MyStuff/my second file.txt

% cat foo.txt | xargs echo
/MyStuff/my first file.txt /MyStuff/my second file.txt

% cat foo.txt | xargs -L 1 echo
/MyStuff/my first file.txt
/MyStuff/my second file.txt

% cat foo.txt | enquote
"/MyStuff/my first file.txt"
"/MyStuff/my second file.txt"

% cat foo.txt | enquote | xargs -L 1 echo
/MyStuff/my first file.txt
/MyStuff/my second file.txt

% cat foo.txt | enquote | xargs rm
rm: /MyStuff/my first file.txt: No such file or directory
rm: /MyStuff/my second file.txt: No such file or directory

The 'enquote' command is actually a Bash function:
Code:

# enquote: surround lines with quotes (useful in pipes) - from mervTormel
enquote () { /usr/bin/sed 's/^/"/;s/$/"/' ; }


fracai 07-14-2009 10:51 AM

Quote:

Originally Posted by kaptagat (Post 542569)
Your find command finds files inside the Adobe folder and deletes them which is not what I want.

Sorry, should have used path.

find . \! -path "*Adobe*" \! -path "*Infected*" -print
find . \! -path "*Adobe*" \! -path "*Infected*" -print0 | xargs -0 rm -r

kaptagat 07-15-2009 06:03 AM

Thanks fracai

I think I have finally got a robust command :-

find /Users/Shared/* \! -path "*/Users/Shared/Adobe*" \! -path "*/Users/Shared/Infected*" -print0 | xargs -0 rm -r

In testing, this keeps "Adobe" but deletes "Adobe folder", "erty adobe hrrkl", "adobe new folder" and "newadobefolder"

Hayne, I can see where you are going and it looks pretty neat but when I use "enquote", it comes back with bash command not found. I use 10.5.7 on a G5.

hayne 07-15-2009 11:00 AM

Quote:

Originally Posted by kaptagat (Post 542689)
when I use "enquote", it comes back with bash command not found

'enquote' is not a standard command - you need to add the line I provided above to your shell configuration files. Or just run the line I provided above in your Terminal window before running the other commands - that defines a Bash function 'enquote'.
Read the section on "shell aliases" in this Unix FAQ

tw 07-15-2009 11:06 AM

I know this is the unix section, but I feel I have to point out that this is really easy in applescript:
Code:

set sharedFolder to path to shared documents from user domain
tell application "Finder"
        set killThese to every item of folder sharedFolder whose name is not "Infected"
        delete killThese
        empty trash
end tell

if you want to skip more than one item, add an "and name is not <itemname>" to the third line for each item you want to save. you can run a similar script on the student's temporary folder; at first blush I'd try something like:
Code:

        set killThese to every item of folder sharedFolder whose kind does not contain "Microsoft" and kind does not contain "Quark" and kind does not contain "Photoshop"

tlarkin 07-15-2009 11:53 AM

find has a lot of over head as it searches your whole drive. When I remove things like programs I typically just set the full path as a variable and do a simple loop to check if that path is there, then if so delete it.

I had used the find command in the past, and yes it is useful but it killed my log in hooks and it killed my log files and caused some problems.

The find command is great when you don't know the path to said files, but if you know the path I say just use the full known path and not use the find command.

jbc 07-15-2009 03:25 PM

With regards to your most recent solution using the find command, I think the fastest and safest option might be something like the following:
Code:

find -E /Users/Shared -mindepth 1 -maxdepth 1 \! -iregex "^/Users/Shared/(Adobe|Infected|\.DS_Store)" -print0 | xargs -0 rm -r
Note that this does not descend into *any* folders within /Users/Shared since you're going to delete their contents (or not) with "rm - r" anyway. You can add anything else you decide to keep (including invisible files like ".DS_Store" as shown; escape any "." chars) by adding them to the name list separated by an OR operator ("|"): "(Adobe|Infected|\.DS_Store|Save This|Don't Trash)". You could use "-prune" here, but it seems redundant since you're already constraining find to looking only at the directory contents of the /User/Shared folder by using "-mindepth 1 -maxdepth 1".

kaptagat 07-16-2009 09:36 AM

Hayne

My script is below :-

#!/bin/sh

enquote () { /usr/bin/sed 's/^/"/;s/$/"/' ; }

cd /Users/Shared
ls | grep -v "Adobe" | grep -v "Infected" > foo.txt
cat foo.txt | enquote | xargs rm -r

This works perfectly when used with LoginWindow Manager so I think I will use it instead of the find command one because I am not really at home with that one.

Thanks to everyone for their replies and help.

tlarkin 07-16-2009 10:00 AM

Quote:

Originally Posted by kaptagat (Post 542901)
Hayne

My script is below :-

#!/bin/sh

enquote () { /usr/bin/sed 's/^/"/;s/$/"/' ; }

cd /Users/Shared
ls | grep -v "Adobe" | grep -v "Infected" > foo.txt
cat foo.txt | enquote | xargs rm -r

This works perfectly when used with LoginWindow Manager so I think I will use it instead of the find command one because I am not really at home with that one.

Thanks to everyone for their replies and help.

To be a bit safer you may want to use the pwd command to make sure it is in the proper folder before you execute any commands.


All times are GMT -5. The time now is 10:19 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.