5

I have a lot of directories and sub-directories. I want to recursively remove one specific file from a directory if it's the only one there. Also assume that there are no sub-directories in that directory. So, to summarize, the assumptions are:

  • The file name is README.TXT (case insensitive)
  • There are no other files or directories in the directory where that file is found

Structure:

 mkdir usecase cd usecase mkdir destroy_this touch destroy_this/readme.txt mkdir do_not_destroy_this touch do_not_destroy_this/readme.txt touch do_not_destroy_this/something-else.txt mkdir do_nothing cd do_nothing mkdir rm_this touch rm_this/README.TXT cd .. mkdir do_nothing_here cd do_nothing_here mkdir has_sub_dir touch README.TXT cd .. 

Running the above would results in this tree structure:

$ tree . . `-- usecase |-- destroy_this | `-- readme.txt |-- do_not_destroy_this | |-- readme.txt | `-- something-else.txt |-- do_nothing | `-- rm_this | `-- README.TXT `-- do_nothing_here |-- has_sub_dir `-- README.TXT 

This is what I've got so far:

find . -type f -iname "readme.txt" -exec sh -c 'ls $(dirname "{}") | wc -l' \; 

The idea is that I count the number of files and directories and if it's one then remove the file.

2 Answers 2

3

What you have is a good base to start. If you modified the contents of your -exec you could introduce a if/then construct which would allow you to act on the state of the count being a 1 or not.

$ find . -type f -iname "readme.txt" -exec \ sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \ then echo "yes"; \ else echo "no"; \ fi' \; no yes yes no 

With this we could expand on the echo "yes" command to perform the actual removal of the file. Something like rm "{}" should do the trick.

Example

$ find . -type f -iname "readme.txt" -exec \ sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \ then echo "removing {}.."; rm "{}"; \ else echo "no"; \ fi' \; no removing ./usecase/destroy_this/readme.txt.. removing ./usecase/do_nothing/rm_this/README.TXT.. no 

Running the above a 2nd time confirms the files are no longer there:

$ find . -type f -iname "readme.txt" -exec \ sh -c 'if [ "$(ls $(dirname "{}") | wc -l)" -eq "1" ]; \ then echo "removing {}.."; rm "{}"; \ else echo "no"; \ fi' \; no no 
1
  • But what if the readme is in a /dir/w/\newline/readme.txt? ls will just error - it wont even read the directory entry. Commented May 31, 2014 at 11:47
2
find . -type f -iname "readme.txt" -exec sh -c ' for f do ls -1qap ${f%/*} | grep -v "\(readme.txt\$\|/\$\|.\{1,2\}\$\)" && echo rm "$f" ; done' \{\} + 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.