3

Oracle Linux 5.10
BASH shell

[oracle@src01]$ getconf ARG_MAX
131072

[oracle@srv01]$ ls -1 | wc -l
40496

#!/bin/bash
#
# delete files in /imr_report_repo that are older than 15-days
find /imr_report_repo/* -maxdepth 0 -type f -mtime +15 |
while read file
do
    rm -f $file 
done

/usr/bin/find: Argument list too long

If I'm reading this right the maximum arguments allowed is 131,072 and I only have 40,496 files in this directory. I haven't checked, but I'm probably trying to delete 40,000 files (over 2-weeks old).

6
  • We're talking about the maximum length of the command line argument (128K in this case)... Remove the * (why would you need that ?) and retry. I'm not sure why you need the while..read loop either... Mar 2 '16 at 20:53
  • @don_crissti is right. in other words: find /imr_report_repo/ -maxdepth 1 -type f -mtime +15 -exec rm {} +. or if you're trying to delete files in immediate sub-directories of /imr_report_repo/ (but not /imr_report_repo itself) then use find /imr_report_repo/*/ -maxdepth 0 -type f -mtime +15 -exec rm {} + - note the trailing / (but note also that this is also subject to ARG_MAX limit of 128Kbytes).
    – cas
    Mar 2 '16 at 21:02
  • @cas Thanks! Please consider moving your comment to an answer.
    – Stringer
    Mar 2 '16 at 21:28
  • Is the -delete option not available in your find?
    – FelixJN
    Mar 2 '16 at 21:48
  • @Fiximan -delete is available, but we have other systems where it is not available. Keeping portability in mind
    – Stringer
    Mar 2 '16 at 21:56
12

I think this has been answered here:

https://arstechnica.com/civis/viewtopic.php?t=1136262

The shell is doing a file expansion of /imr_report_repo/* , which causes the problem. I had a similar issue which I fixed by changing the find command from

find /imr_report_repo/* -maxdepth 0 -type f -mtime +15 

to

find /imr_report_repo/ -name "*" -maxdepth 0 -type f -mtime +15 

The quotes keep the shell from expanding the wildcard and then find can use it as a regular expression. It also helps if you need to search for a large number of files that match a specific criteria (like "*.foo").

1

The maximum command line length is the total size in bytes, not the number of arguments. 40k files with names of the form /imr_report_repo/* means a minimum of about 800kB, probably more. That's over the limit.

The obvious solution is to make find do the recursion for you. Go from depth 1 to depth 1 instead of depth 0 to depth 0.

find /imr_report_repo/ -mindepth 1 -maxdepth 1 -type f -mtime +15 -delete

Unlike the original, this includes files whose name begins with . (dot files). If you don't want that, exclude them:

find /imr_report_repo/ -mindepth 1 -maxdepth 1 -name '.*' -prune -o -type f -mtime +15 -delete

Most find implementations that have -maxdepth also have -delete. If yours doesn't, don't just pipe the result into while read: it's somewhat slow and breaks on file names containing newlines (and backslashes and trailing whitespace because you used read where you should have used IFS= read -r). Use -exec, that's what it's for.

find /imr_report_repo/ -mindepth 1 -maxdepth 1 -type f -mtime +15 -exec rm -f {} +
0

Try: find /imr_report_repo/ -maxdepth 1 -type f -mtime +15 -exec rm {} + or, as suggested by @Fiximan, find /imr_report_repo/ -maxdepth 1 -type f -mtime +15 -delete

If you're trying to delete files in immediate sub-directories of /imr_report_repo/ (but not /imr_report_repo itself) then use find /imr_report_repo/*/ -maxdepth 0 -type f -mtime +15 -exec rm {} + (or ... -delete) - note the trailing /

note also that this is also subject to ARG_MAX limit of 128Kbytes.

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.