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.
    – mikeserv
    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.

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