Find and rm files with spaces in the name

I'm sure this has been answered before, but my searches have not turned up the right solution. :confused:

I need to remove files in a directory, without descending into subdirectories, older than n days. Some of the filenames contain spaces or other special characters:

E10403 (2)
E20402 (2)
W50301 (2)
Shortcut to enew1.lnk

So far all variations of find I've tried result in The parameter list is too long (e.g. find * -prune -type f -mtime +30).

Suggestions or links to solutions would be much appreciated. :slight_smile:

TIA
Lee Carlson (aka PapaLee)

The way to avoid too many arguments is to not cram too many arguments into something.

This is wrong:

find *

This is good:

find ./

Thanks for the reply, however ...

# find ./ -prune -print
# find ./ -prune
./
# find ./ -prune -print
./
# find ./* -prune -print
ksh: /usr/bin/find: 0403-027 The parameter list is too long.

Doesn't seem to help.

ls | grep " " | while read ff; do rm "$ff"; done

Try adding a file type to the find command and then couple that with achenle's suggestion: ( in place of ls )

find . -type f -prune -mtime -30

This eliminates the The parameter list is too long error.

find . -type f -prune

-type f ahead of -prune

However, it descends into the subdirectories, which violates one of the primary requirements. It needs to be confined to the current directory without descending into subdirectories.

Good

-maxdepth 1 limits the recursion:

find . -maxdepth 1 -type f -prune -mtime -30

Entire command: Works here... ( change echo to rm when safe )

find . -maxdepth 1 -type f -prune -mtime -30 | grep " " |while read ff; do echo "$ff"; done

I didn't mention this is AIX 5.3.

Apparently -maxdepth is not a valid option on this flavor of AIX. :frowning:

# find . -maxdepth 1 -prune -type f
find: 0652-017 -maxdepth is not a valid option.

Well...ain't that somethn'

There is an -xdev option: ( the order matters as you know )
Change echo to rm if it works...

find . -xdev -type f -name "* *" -exec echo {} \;

Have a look here and locate the find command.
AIX Commands Support Tips
or
IBM Systems Magazine - Search Smarter with the find command | AIX | IBM Systems Magazine | System p, System p5, Power System | find, command, search

Find every file that meets your mod time/age requirement, use "sed" to remove the leading "./" characters, remove any names that still have a '/' directory separator in them, and remove what's left:

find . -mtime N -type f -name '* *' | sed 's/\.\///g' | grep -v '/' | while read ff; do rm "$ff"; done

Been busy in meetings and calling it a day - finally. Will take a look at the recent suggestions tomorrow and let you know the results.

Again, thanks for the suggestions/examples. At the very least I'm learning more about this environment and sharpening the knife of my *NIX knowledge. :slight_smile:

The find -xdev primary only helps if the subdirectories are all mount points for different filesystems. However, the following command should do what you want:

find . \( -type d  ! -name . -prune \) -o \( -type f -name '* *' -mtime +30 -exec echo rm {} + \)

If the output correctly shows the rm command (or commands) you want to run, remove the echo and rerun the find .

1 Like

It doesn't matter where you put the asterisk - as long as you put it anywhere it will expand to a long (and obviously too long) list of filenames.

The suggestion was to avoid the asterisk altogether, not to put it somewhere else in the command.

bakunin

You are not printing anything because you're -prune-ing them all.

And then, you cram in too many arguments again, causing it to die from too many arguments.

Stop doing that.

find ./

Using find * was suggested from another source. At first it seemed to do what was needed. In fact, executing it in a directory where none of the file names contain spaces or something that's appearing as a space does work as advertised.

---------- Post updated at 12:17 PM ---------- Previous update was at 12:09 PM ----------

Don,

Your suggestion

find . \( -type d ! -name . -prune \) -o \( -type f -name '* *' -mtime +30 -exec echo rm {} + \)

works. Thank you.

For my edification, what does the + do in rm {} + \ ?

There are two forms of -exec:

-exec command ...'{}'  ';'

and

-exec command ... '{}' '+'

{} ; means "run command once per file". {} + means "run command once for many files". So ';' will run rm file1 , rm file2 etc. while '+' will run rm file1 file2 file3 .. It keeps the maximum number of arguments in mind, but puts in as many as safely possible in one command for efficiency.

1 Like