![]() |
delete all files except....
Hello Everyone
I need a script to run on logon which will delete everything in /Users/Shared/ except a folder called "Infected" I have tried rm -R *.* !(Infected) but it comes back with !: event not found. Secondly, to try to keep the students temporary folder reasonably "clean" I use a script like the one below :- rm -R *.app *.zip *.dmg *.pkg Can anyone suggest any other "nasty" extensions i should delete. The only stuff in there should be office 2008 work, CS4 and Quark work. I also run a script on this folder which deletes everything over 1 month old. thanks thanks |
You should use a script (not a one-line command) with a loop and an 'if' statement to select which folders you want to delete (or not).
|
I have a search and destroy scripts for such things, but you will need to modify mine. You will have to set the path to the exact folder you want it to search and destroy that way it isn't indexing the whole root drive and take forever to run.
http://tlarkin.com/tech/search-and-destroy As for the /users/Shared you could write a loop and use even parts of that script I posted |
Quote:
The OS X filesystem is case-preserving, but case-insensitive. However the case-insensitivity only means that if you ask it to delete a file "foo.mp3", it will work to delete the file "foo.MP3" - but your script doesn't ask that. It explicitly only searches for files with lowercase suffixes. You could fix this by simply changing to use "-iregex" instead of "-regex". |
Quote:
I will make the change you suggested. Thanks. |
Anytime you have a script like this, I would strongly suggest that you have another script that sets up a bunch of test cases and then runs your script to check that it works on those test cases. And then when you find a bug in your script (e.g. that it doesn't delete ".MP3" files, you add a new case in your test script so that all future versions of the script will be checked to ensure that they work for that case as well.
|
The only problem I found is that the find command with the -print option spams the console, so I typically take it off once I see that it works, and I typically also use the -print command before the -delete one to make sure it works.
I just did a few audits and I didn't see any all caps file extensions on the file shares, but that doesn't mean they don't exist. It just had never occurred to me. |
I am trying a variation of the script I am using to delete files in the student's temporary folder which are older than a month which is :-
find "/Student's Temporary Folder/" \! -newermt '1 month ago' -delete So to delete all the stuff in the shared folder except one folder called say, Adobe, I tried this :- find /Users/Shared/ \! -path */Adobe/* -delete but this deletes everything and comes back with the message :- find: -delete: /Users/Shared/: relative path potentially not safe I tried /Users/Shared/ \! -name */Adobe/* -delete but this keeps the Adobe folder BUT deletes everything inside which I expected. Why is it so hard to delete everything except a certain folder? |
Quote:
Try something like: find /Users/Shared/ \! -path '*/Adobe/*' -print |
Quote:
|
Quote:
When I use find /Users/Shared/ this comes back :- /Users/Shared/ /Users/Shared//.dateFile.plist /Users/Shared//.DS_Store /Users/Shared//Adobe /Users/Shared//Adobe/test.txt Then when I try find /Users/Shared/ \! -path '*/Adobe/*' -print This comes back :- /Users/Shared/ /Users/Shared//.dateFile.plist /Users/Shared//.DS_Store /Users/Shared//Adobe It still finds the Adobe folder but strangely not its contents. One solution would be to make the Shared folder read only. Would this cause any unexpected problems? |
Quote:
Code:
find /Users/Shared \! -path '*/Users/Shared/Adobe*' -print |
Thanks a million JBC, works a treat!
|
Cool. But looking at what I posted I realized that it will possibly skip some unwanted files: for example, a folder in /Users/Shared/ named "Adobe Reader" and its files would not be deleted.
I think the following is what you want: Code:
find /Users/Shared \! \( -path '*/Users/Shared/Adobe/*' -or -path '*/Users/Shared/Adobe' \) -print |
Quote:
[note: the folder must be exactly named Adobe, no spaces or control chars, etc.] Or, are you saying -ls and -delete are finding different files on your Mac? |
Skipping more than one folder:
find -xE /Users/Shared -not \( -regex '.*/(Adobe|Infected|Library)' -prune \) -ls ^ skips "Adobe" folder, and "Infected" folder (from post#1), and a "Library" folder. Add more folders using the vertical bar | i.e., the ERE "or" symbol (same char as a pipe). If case-insensitive matching is desirable, use iregex instead. If skipping folders whose name start with Adobe (etc.) is desirable, add .* find -xE /Users/Shared -not \( -regex '.*/(Adobe|Infected|Library).*' -prune \) -ls -HI- |
Quote:
On a side note I just learned that if your case sensitivity is off, it won't find the file. Hayne pointed out to me that if you use -iregex it will search both upper and lower cases. Just a FYI. |
Quote:
Otherwise, yes... had case been specified, iregex is surely what I would have recommended. [and -- having read post #4 above -- my previous message already raised the issue, FYI. ;) ] |
Quote:
A lot of times I forget about little things like that |
Thanks to everyone for all your replies and Hal Itosis for your command works well and it is very useful to exclude additional folders by using "|".
The "find" command is obviously very powerful but its syntax reminds me of Egyptian hieroglyphics. I now want to use it to sweep the Student's temporary folder of applications as it should work better than "rm *.app" because this doesn't remove any applications inside folders. 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. Any ideas why? |
Are you sure it's not deleting anything? Or just not printing the result?
add -print before -delete and try it again. |
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 |
So no one can suggest a reason why the found applications are not deleted?
Thanks in Anticipation. |
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. |
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). |
Quote:
"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.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 |
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. |
Quote:
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 |
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 |
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. |
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. |
Look at the following - it should help you to figure out a solution to your problem:
Code:
% cat foo.txtCode:
# enquote: surround lines with quotes (useful in pipes) - from mervTormel |
Quote:
find . \! -path "*Adobe*" \! -path "*Infected*" -print find . \! -path "*Adobe*" \! -path "*Infected*" -print0 | xargs -0 rm -r |
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. |
Quote:
Read the section on "shell aliases" in this Unix FAQ |
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 domainCode:
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" |
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. |
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 |
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. |
Quote:
|
| 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.