List and Delete Files which are older than 7 days, but have white spaces in file name

I need to list and delete all files in current older which are olderthan 7 days. But my file names have white spaces. Before deleting I want to list all the files, so that I can verify.

find . -type f -mtime +7 | xargs ls -l {}

But the ls command is the working on the files which have white spaces.

Any other ideas ?

The solution is simple: stop using xargs .
If you want a long listing of files that find finds that meet your criteria, try:

find . -type f -mtime +7 -exec ls -l {} +

and if you want to get a long format listing of the files and also remove them, try:

find . -type f -mtime +7 -exec ls -l {} \; -exec rm {} \;

If you had a file named a b that hasn't been modified for more than 7 days, the command you used would try to give you a long format listing for files named a and b instead of the file named a b .

Thank you.
Just for understanding, what does " + "do in the command

The command:

find -type f -exec utility initial_arguments... {} +

in the specific case using -exec ls -l {} + invokes the ls utility with the -l option and operands specifying the names of one or more files (but limited to a number of operands that will not cause the invocation to fail due to an argument list too long error).

Using a semicolon instead of a plus sign to terminate the -exec primary will invoke the ls utility for each file instead of grouping a number of files together as operands to a single invocation of ls . (And, the semicolon has to be escaped or quoted, because it has special meaning to the shell.)

Probably in your case -mtime +7 is sufficient.
But it would have problems with files that are extracted from a tar or zip archive, getting a time stamp from the past (or the future).
In this case -ctime +7 is an improvement.
But a regular file backup (or virus scan) can reset atime (for convenience), and ctime changes.
The following is robust with archives and weekly full backups: \( -mtime +7 -o -mtime -0 \) -ctime +5 , and run daily.

I want to remove the files with the pattern *.__* but need to eliminate the files which contains "ABC" and "XYZ". SO framed a syntax like below. Will this work ?

find . -name "*.__*" -mtime +60 -exec ls -lrt {} + | grep -iv "ABC" | grep -iv "XYZ" ; -exec rm {} \; 

---
AIX 7.1

find . -name "*.__*" -mtime +60 ! -name "*[Aa][Bb][Cc]*" ! -name "*[Xx][Yy][Zz]*" -exec rm {} \;
1 Like

I assume that the question was rhetorical and that you already know that it won't work. If I understand what you're trying to do, try this:

find . -mtime +60 -name '*[.]__*' ! -name '*[aA][bB][cC]*' ! -name '*[xX][yY][zZ]*' -exec echo rm {} +

If the rm command(s) printed look(s) like it(they) do(es) what you want, remove the echo from the find -exec primary to actually remove the selected files.

1 Like

Thank you. It worked but I missed my criteria - I need to exclude the "ABC" and "XYZ" directory contents in the above recursive command output. Any idea ?

---------- Post updated at 02:57 AM ---------- Previous update was at 02:52 AM ----------

Based on the above Inputs I framed like below to list and delete the files :

find . -name "*.__*" -mtime +60 ! -name "*[aA][bB][cC]*" -name "*[xX][yY][zZ]*" -exec ls -lrt {} \; -exec rm {} \

But to be clear, I need to exclude "ABC" and "XYZ" directories not file names. Sorry for the confusion.

Thanks.

I don't understand why you thought you needed grep -iv ABC if you just wanted to toss the contents of the directory named ABC ...

Does this work with your new requirements?

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec rm {} + \)

I thought grep -v will eliminate the required directories as we will have the long listing. It doesn't work.

The above one looks working, I just modified the given one like below so that it can list and then remove.

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} \; -exec rm {} \;)

Hope this is correct, I cant test it - because if some thing went wrong I may messup the file system. Hence asking whether it is ok or not.

If you want to test it without making any changes to the file hierarchy, put an echo in front of the rm :

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} + -exec echo rm {} + \)

Note that with -exec ls -lrt {} \; , the -r and -t are meaningless. With -exec ls -lrt {} + , groups of files will be sorted in reverse time order; but there is no guarantee that all of the files you want to process will be processed by a single invocation of ls .

If the ls output and the echo output shows that it is selecting the files you want to remove, take out the echo to actually remove the selected files.

Note also that if you want to run slower and take more system resources, you can use -exec rm {} \; instead of -exec rm {} + , but you can't combine \; and \) into \;) as you did in your script.

Some how the rm is not executing in the above command, it is listing all the files but not removing. I have removed echo command.

Strange. Please show us the exact output you get when your run the commands:

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} + -exec rm {} + \) > out1.1 2> out2.1
find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} + -exec rm {} + \) > out1.2 2> out2.2
ls -l out[12].[12]
for i in 1 2
do      echo "** out2.$i"
        cat out2.$i
done

I am capturing the output to a log and following are the outputs :

Run 1: out1.1 :
Files older than 60 days :
-rwxrwxrwx    1 test_user test_user          0 Nov 09 18:28 ./Test/one1.__0
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__9
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__8
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__7
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__6
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__5
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__4
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__3
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__2
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__1
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__0
Run 2: out1.2
Files older than 60 days :
-rwxrwxrwx    1 test_user test_user          0 Nov 09 18:28 ./Test/one1.__0
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__9
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__8
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__7
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__6
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__5
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__4
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__3
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__2
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__1
-rwxrwxrwx    1 test_user test_user          0 Dec 08 17:29 ./Test/November 2014.__0

There are no errors i.e; out2.1, out 2.2 both are empty files.

Looking more closely at the standard, when using -exec command + , the primary always returns success even if one or more executions of the given command fail. Furthermore, if there are two or more primaries like this, the order in which they are executed is unspecified. (So, the rm commands for a group of files could be executed before, after, or simultaneously with the ls commands for the same or different groups of files.) I don't understand why this would keep the rm commands from working, but it could cause files to be removed before they were listed by ls .

When the echo was in the -exec echo rm ... , did you see any output from the echo ?

Does the following semicolon version work?

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} \; -exec rm {} \; \)

If not; what is the output from the command:

find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} \; -exec echo rm {} \; \)
1 Like
 
find . \( -name ABC -prune \) -o \( -name XYZ -prune \) -o \( -name "*.__*" -mtime +60 -exec ls -lrt {} \; -exec rm {} \; \)

This worked. Thank you Don!