Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
add comment

2 Answers 2

up vote 3 down vote accepted

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
share|improve this answer
    
But what if the readme is in a /dir/w/\newline/readme.txt? ls will just error - it wont even read the directory entry. –  mikeserv May 31 at 11:47
add comment
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' \{\} +
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.