0

I got a folder that has a whole bunch of subdirectories.

I need to delete all of them EXCEPT folders that has a marker file say example: DONOTDELETE.txt inside the said folders.

Is this possible?

Already had a presolution Thanks to Benoit

( find /testftp -type d ;
  find /testftp -type f -iname DONOTDELETE.TXT -printf '%h'
) | sort | uniq -u | while read i
                     do
                        rm "$i/*";
                     done

but the output is:

rm: cannot lstat `/testftp/*': No such file or directory

rm: cannot lstat `/testftp/logs/*': No such file or directory

4
  • Yes, it's possible. Are you expecting one of us to write it for you?
    – Nifle
    Feb 23, 2012 at 16:26
  • Just asking for help Nifle. that would really be appreciated if you can give me an idea on this. Kinda new to scripting to be honest Feb 23, 2012 at 16:27
  • Start looking at what find can do. Use that in conjunction with dirname to find all dirs you want to leave alone.
    – Nifle
    Feb 23, 2012 at 16:33
  • Update your question (or better yet delete this one and ask a new) when/if you get stuck or have a partial solution.
    – Nifle
    Feb 23, 2012 at 16:36

3 Answers 3

2

As shell fragment:

for i in *; do
     [ -d "$i" ] || continue # ignore non-directories
     [ -f "$i/DONOTDELETE.txt ] && continue  # ignore directories containing DONOTDELETE
     rm -rf "$i"
done
7
  • Hi Jakob...im new to scripting..can you explain further? :) Feb 23, 2012 at 19:32
  • I'm confused at the moment lol... Feb 23, 2012 at 21:42
  • Sorry for the delay :)
    – jakob
    Feb 24, 2012 at 11:45
  • Every unix shell descended from the original bourne shell has control flow statements - while, for, if/else etc. In this case, for is used. * expands to a list of files, and the for body is executed for every file. "[" is a executable (look for /bin/[). It is also available under the name "test", read "man test". -d checks whether the next thing is a directory; -f checks whether the next ting is an ordinary file. "continue" is a bash control flow construct, it behaves exactly like "continue" in java or c.
    – jakob
    Feb 24, 2012 at 11:46
  • Any more specific questions?
    – jakob
    Feb 24, 2012 at 11:50
1

How I would do that (maybe overcomplicated):

  • Find all dirs
  • Find all files named DONOTDELETE.TXT and print dir names
  • Sort and uniq to keep unique lines

So:

( find . -type d ;
  find . -type f -iname DONOTDELETE.TXT -printf '%h'
) | sort | uniq -u | while read i
                     do
                        rm "$i/*";
                     done

Warning, if you have the following tree:

A/foo.txt
A/b/DONOTDELETE.TXT

Then the output of this last script will still output A because it does not contain a file named DONOTDELETE.TXT.

Another way:

find . -type f ! -iname DONOTDELETE.txt -delete
find . -d -type d -empty -delete

which first nukes all files that don't have this name, and second removes empty directory (-d explores subtrees first).

7
  • Really confused right now...sorry for being such a newb... wanted to delete all files under /ftptest except files that doesn't have the DONOTDELETE.TXT and your code seemed to be great...just really confused ATM. so sorry Feb 23, 2012 at 17:14
  • find /testftp -type f ! -iname DONOTDELETE.txt -delete <--This worked for me. I had a /testftp/logger/ which contains DONOTDELETE.TXT and test.txt, It still deleted the test.txt, would like to happen to keep test.txt I really appreciate the contribution you gave Benoit Feb 23, 2012 at 17:21
  • @JoyIanYee-Hernandez can you possibly have trees like the one I showed in my answer? Directory not containing the marker, having a subdirectory containing the marker? Should foo.txt be nuked or not?
    – Benoit
    Feb 23, 2012 at 17:28
  • With this ( find /testftp -type d ; find /testftp -type f -iname DONOTDELETE* -printf '%h'; ) | sort | uniq -u I got a tree: /testftp /testftp/logs <--- this directory does not contain the DONOTDELETE.TXT this is pretty close, just need to delete all the files inside that /testftp/logs folder Feb 23, 2012 at 17:36
  • So, pipe that command into while read i ; do rm "$i/*" ; done.
    – Benoit
    Feb 23, 2012 at 17:37
-3
find . -type f ! -name DONOTDELETE.txt  -print0 | xargs -0 ls -l
3
  • 2
    No, that will list files of which the name is different, but will still list files in the same directory.
    – Benoit
    Feb 23, 2012 at 17:01
  • Yes. I'm trying to get a hang of the find command. I tested this out and yeah it still lists the files that I wanted to keep. I'm playing around it and wanting for the specific folder to not exist on the ls -l and wanting to expect that folder that contains DONOTDELETE.txt won't come up Feb 23, 2012 at 17:03
  • Rephrase question again and more and more people will jump in to help....
    – ZaB
    Feb 24, 2012 at 8:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .