I'm trying to chown all files whose filenames begin with ChownFileNames. I've used this command, but it doesn't seem to work:

find . -maxdepth 1 |grep 'ChownFileNames*' -exec chown hadoop:hadoop -- {} . \;

What am I doing wrong?

chown hadoop:hadoop ChownFileNames*

This should work for what you need:

find . -maxdepth 1 -iname 'ChownFileNames*' -exec chown hadoop:hadoop -- {} . \;
  • 2
    it's much better to use \+ instead of \; in such cases. It will start one process per multiple files insted of one process per file, therefore the job will be done much faster on large amount of files. – rush Jun 20 '12 at 13:01
  • If you're doing this for a directory, lose the dot (.) after {}, add recursive -R, and add -type option to find: find . -type d -maxdepth 1 -iname 'ChownFileNames*' -exec chown -R hadoop:hadoop -- {} \;. To find in current as well as all sub folders, lose -maxdepth 1. – Qumber Aug 19 '20 at 6:48

The | (“pipe”) symbol means to pass the output of the command on the left to the command on the right. The command find . -maxdepth 1 lists the files in the current directory (plus . itself). The command grep 'ChownFileNames*' -exec chown hadoop:hadoop -- {} . \; doesn't make any sense: you're passing find options to the grep command.

find itself has a way to match file names, the -name predicate. It takes a shell wildcard pattern as argument.

You could use grep to filter the list, but you'd have to provide a valid command line to grep. To retain only file names matching the shell pattern ChownFileNames*, you would need to use the regular expression /ChownFileNames[^/]$. Then you would have to parse the output of grep to transform the list of matching names into command line arguments. Assuming that you're running Linux and the file names do not contain any newlines, you could use xargs:

find . -maxdepth 1 |
grep '/ChownFileNames[^/]*$' |
xargs -d '\n' chown hadoop:hadoop

It is a lot simpler and more robust to use find's -exec action. Note that you can use -exec … {} + to run the command for a batch of files at once instead of once per file. You can also make find list the current directory.

find . maxdepth 1 \( -name . -o -name 'ChownFileNames*' \) -exec chown hadoop:hadoop {} +

There's usually no point in running find when you're only matching files by name (and not e.g. by date) in the current directory (without traversing subdirectories). Unless there are so many files in the current directory that this makes the command line too long, just use

chown hadoop:hadoop . ChownFileNames*

Please take a look at the -name or -iname options in find(1)

  • And , especially, -exec option :) – Sergei Lomakov Jun 20 '12 at 11:32

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.