Ethanopp
Ethanopp

Reputation: 73

find: chown: Argument list too long

I am trying to change the permissions on all files with group or owner 1001 to 1000.

I've tested these 2 commands on a small directory and they both work, but when I try using them all the way from root, I get the 'argument list too long' error

find /share/CACHEDEV2_DATA/Container -user 1001 -exec chown 1000 {} +
find /share/CACHEDEV2_DATA/Container -group 1001 -exec chgrp 1000 {} +

Is there a different way I can execute the command to get around this error?

Upvotes: 2

Views: 2592

Answers (3)

amit kawade
amit kawade

Reputation: 11

This works:

chown -R john:build /tmp/src

Upvotes: 1

dash-o
dash-o

Reputation: 14452

Short version:

Given number of files, placing all arguments on a single command will fail (too many arguments, or too long command line). Using xargs to batch lines will solve the line length problem, and improve the performance.

# Preferred - using NUL to separate files
find /share/CACHEDEV2_DATA/Container -user 1001 -print0 | xargs -0 -L50 chown 1000

# Without protection against "special" file names (risky)
find /share/CACHEDEV2_DATA/Container -user 1001 | xargs -L50 chown 1000

Long Answer:

As indicated by some commentors, the source of the problem is the trailing '+' (instead of the more commonly used trailing ';') to the find command. From info find

... The SVR4 edition of Unix introduced a slight variation, which involves terminating the command with '+' instead:

 find /var/tmp/stuff -mtime +90 -exec /bin/rm {} \+

The above use of '-exec' causes 'find' to build up a long command line and then issue it. ...

So find offers two bulking options - one file per line, and ALL files per line.

Clearly, this is a case to integrate with 'xargs', which provide more flexible way to batch lines - by argument count (-L...) or line size (-s). Also, should consider using the null terminator to support situation where file names have spaces, magic characters ('*'), etc.

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207485

You can do that with GNU Parallel quite simply and efficiently if you use the -X option which passes as many arguments as your system's ARGMAX allows.

I am not at a machine to check this, so try it on a small directory with a copy of just a few files before you let rip through a whole filesystem:

find <STARTDIRECTORY> -user 1001 -print0 | parallel --dry-run -X -0 chown 1000 {}

If that looks correct, run it again but omitting the --dry-run.

Upvotes: 1

Related Questions