find /apps/dynalife/clients/. ! -path "train" -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" \) -exec {} \; > /apps/dynalife/util/delFile.lst

I am trying to find all files older than 90 days in /apps/dynalife/clients/ and all subfolders. But I exclude the subfolder /apps/dynalife/clients/train/ and I also want to exclude all files with extensions ending in one of a few values p / i / w / cls / inf / bat

The script is just producing an empty file.

The idea is to have a file I can check and then use as input for the rm command to remove all the files found.

Updated Find:

find /apps/dynalife/clients/ ! -path "*/mapwrk/*" -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" -o -name "*.ini" -o -name "*.pf" -o -name "*.wob" -o -name "*CIM900*" \) -print > /apps/dynalife/util/delFile.lst

Updated Delete:

xargs rm < /apps/dynalife/util/delFile.lst

You only pass the filename to -exec so that does not do anything. You need to use -print0 so you also can handle filenames with newlines and other special characters, so do something like:

find /apps/dynalife/clients/. ! -path "train" -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" \) -print0 > /apps/dynalife/util/delFile.lst

That will give you a list that you can feed into rm using:

cat /apps/dynalife/util/delFile.lst | xargs -0 rm

If your find does not support -print0 and your filenames do not contain newlines (but spaces) you can use -print:

find /apps/dynalife/clients/. ! -path "train" -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" \) -print > /apps/dynalife/util/delFile.lst


cat /apps/dynalife/util/delFile.lst | xargs rm
  • NOT WORKING. find: 0652-017 -print0 is not a valid option – AquaAlex Dec 9 '13 at 11:54
  • 3
    -print0 is a GNUism (IIRC); you'll have to use -print instead, which will break on filenames containing newlines. -print0 seperates the files with nullbyte, which is the only character that cannot appear in a file path according to the standards and so is bulletproof; -print seperates with newlines, and so will break if your filenames contain newlines (which I've never seen outside of files created specifically to test scripts). – evilsoup Dec 9 '13 at 12:04
  • @evilsoup thank you, give me same results as the echo option. So all working – AquaAlex Dec 9 '13 at 12:17
  • You've got some UUOCs, the argument to -path has to be a path, not just a name, for xargs, you need to escape space, tab, single quote, double quote and backslash characters in addition to newlines. – Stéphane Chazelas Dec 9 '13 at 12:57
  • cat /apps/dynalife/util/delFile.lst | xargs -0 rm does not work --> xargs rm < /apps/dynalife/util/delFile.lst worked – AquaAlex Dec 9 '13 at 14:21

The argument to -path is to match the path. -path trains would never match anything.

find /apps/dynalife/clients ! -path '/apps/dynalife/clients/trains/*' \
  -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" \
  -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" \
  \)  > /apps/dynalife/util/delFile.lst

Though, if you don't intend to find any file in trains, you might as well prune it to avoid descending in it:

find /apps/dynalife/clients -path /apps/dynalife/clients/trains -prune -o \
  -type f -mtime +90 ! \( -name "*.p" -o -name "*.i" -o -name "*.w" \
  -o -name "*.cls" -o -name "*.inf" -o -name "*.bat" \
  \) -print > /apps/dynalife/util/delFile.lst

Assuming none of the file names contain newline characters, you can remove them with:

sed 's/./\\&/g' < /apps/dynalife/util/delFile.lst | xargs rm -f

Here, we're escaping every character (but newline) so that they are not considered specially by xargs. Strictly speaking, only:

sed "s/[\\' \"$(printf '\t')]/\\\\&/g"

is needed (that is, only space, tab, backslash, single and double quotes need escaped).

  • actually /train/ works perfectly, especially since the path could be in any position – AquaAlex Dec 9 '13 at 14:22
  • there is an * before and after / all files in that folder and its subfolders are skipped – AquaAlex Dec 11 '13 at 7:00
  • @AquaAlex, yes though that would skip the files in all the folders called train, not just /apps/dynalife/clients/train, and find still descends into those which is why you may want to use -prune as an optimisation. – Stéphane Chazelas Dec 11 '13 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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