Klaus Rolland
Klaus Rolland

Reputation: 11

subsequent calls of 'rm -rf' not working in 'for' loop

I want to delete several folder found by find. This script works fine only in the first loop in for. The echo shows that the loop is working fine, but the rm -rf $f is not executed in the second and subsequent loops.

folder=`find /seriem/docs/it/ -name '*.printed' -printf '%h\n'`

for f in $folder
do
    echo "rm -rf $f"
    rm -rf $f
done

In my case the debug output is:

rm -rf /seriem/docs/it/afp/PC_58
rm -rf /seriem/docs/it/afp/PC_59
rm -rf /seriem/docs/it/afp/PC_60

but only folder PC_58 is deleted.

Sorry if I made something wrong in this post... it's my first on stackoverflow ;)

Working solution:

for f in $(find /seriem/docs/it.nrw/ -name '*.printed' -printf '%h\n');
do
    echo "rm -r $f"
    rm -r -v "$f" 

    #do some other stuff. This is why I need a loop
done

Hopefully I did it right now ;) Thanks for all your fast help !!!!

Upvotes: 1

Views: 322

Answers (4)

tripleee
tripleee

Reputation: 189477

If the intent is to remove the entire containing directory when a match is found;

find /seriem/docs/it/ -name '*.printed' -execdir rm -rf {} \;

Upvotes: 0

Léa Gris
Léa Gris

Reputation: 19585

You can have find handle the whole delete process in a safe way for you:

#!/usr/bin/env/bash

find /seriem/docs/it/ -regex '/seriem/docs/it/.*\.printed\(/.*\)?' -delete
/seriem/docs/it/

Find arguments split-out:

  • find: the command
  • /seriem/docs/it/: base directory to start the search
  • -regex '/seriem/docs/it/.*\.printed\(/.*\)?': the RegEx pattern to apply to the whole path:
    • /seriem/docs/it/: path start with this literal
    • .*: any number of any character
    • \.printed: literal .printed
    • \(/.*\)?: optional group of / followed by any character
  • -delete: performs deletion of the found/matched files

Upvotes: 0

chepner
chepner

Reputation: 531325

You don't need a loop at all. Use -exec.

find /seriem/docs/it/ \
     -name '*.printed' \
     -exec sh -c 'rm -rf "$(basename "$1")"' _ {} \;

To avoid forking a separate shell for each call to rm, put a loop in that shell to iterate over the shell's parameters, and use the -exec ... + form to pass as many files as possible to each shell.

find ... -exec sh -c 'for f; do rm -rf "$(basename "$f")"; done' _ {} +

Either approach ensures that the file name is properly quoted before being passed to rm.

Upvotes: 1

RedXIV
RedXIV

Reputation: 23

the $f should be in quotes

rm -rf "$f" 

rather than

rm -rf $f

is safer.

EDIT: @Kamil Cuk beat me to it

Upvotes: 0

Related Questions