3

I often use

ls -ld .
# remember current user and group
chown -R user.group .
chown remembered_user.remembered_group .

Isn't there an easier way to recursively chown all files and directories in a directory but not the directory itself? It should include hidden files and work no matter how many files there are.

4

You can use find to avoid the argument list being too long, while still passing as many arguments to chown in one go as possible (using + instead of ;). -prune allows you to remove some unneeded arguments to chown (it won't descend directories, it will just use chown -R on them):

find . \! -iname . -prune -exec chown -R user:group {} +
1

Why not just run chown inside the directory recursively.

$ chown -R user.group *

Example

. directory before.

$ ll
total 20
drwxrwxr-x. 2 saml saml 4096 Apr  9 22:30 dir1
drwxrwxr-x. 2 saml saml 4096 Apr  9 22:30 dir2
drwxrwxr-x. 2 saml saml 4096 Apr  9 22:30 dir3
drwxrwxr-x. 2 saml saml 4096 Apr  9 22:30 dir4
drwxrwxr-x. 2 saml saml 4096 Apr  9 22:30 dir5

Change just the contents of dir.

$ chown -R saml.wheel *

Contents after.

$ ll
total 20
drwxrwxr-x. 2 saml wheel 4096 Apr  9 22:30 dir1
drwxrwxr-x. 2 saml wheel 4096 Apr  9 22:30 dir2
drwxrwxr-x. 2 saml wheel 4096 Apr  9 22:30 dir3
drwxrwxr-x. 2 saml wheel 4096 Apr  9 22:30 dir4
drwxrwxr-x. 2 saml wheel 4096 Apr  9 22:30 dir5

Meanwhile the directory, . is left intact.

$ ls -ld .
drwxrwxr-x. 7 saml saml 4096 Apr  9 22:29 .

If there are hidden files, make sure to set up your shell to include them in the glob: shopt -s dotglob in bash, FIGNORE='@(.|..)' in ksh93, setopt dot_glob in zsh.

Alternatively, add a pattern that matches them (beware that in shells other than zsh, .* would match . and ..):

chown -R saml.wheel * .[!.]* ..?*

Or in zsh, simply

chown -R saml.wheel *(D)
  • argument list too long – AndreKR Apr 10 '14 at 3:03
  • 1
    And it doesn't affect hidden files either. Not an answer, sorry. – AndreKR Apr 10 '14 at 3:04
  • @AndreKR - without knowing anymore about the nature of your directory this was a valid A. – slm Apr 10 '14 at 11:28
  • @AndreKR - Gilles added how to include the dotted files/directories using chown -R. – slm Apr 10 '14 at 21:45
  • It was in the question: It should include hidden files and work no matter how many files there are. – AndreKR Apr 10 '14 at 22:58
1

You can use the following:

find . -mindepth 1 -print0 | xargs -0 chown user:group

Edit: The problem with your example above is that you are operating on the current folder (.). The mindepth section of my example excludes the current folder from the list of files/directories that are going to be modified.

Print0 changes the find output to be null-terminated, and xargs operates on each line (or null-terminated string, with -0) and runs the specified command with your input at the end (in this case, each file name). You could change the xargs command to be more explicit like this:

xargs -0I {} chown user:group {}

That way, you can put find's output anywhere you want in your command.

0

In zsh:

chown user:group **/*(D)

The glob qualifier D means that dot files will be matched.

You can make chown do the recursive traversal instead of the shell:

chown -R user:group *(D)

If you're worried that there are so many files that the command line will be too long, load the chown builtin from the zsh/files module.

zmodload zsh/files
chown user:group **/*(D)

If you don't want to make chown refer to the builtin, you can load only the zf_* names:

zmodload -Fm zsh/files b:zf_\*
zf_chown user:group **/*(D)

When you need to call an external command (which isn't the case here) on a long list of files that might not fit in the command line limit, you can use the zargs function:

autoload -U zargs
zargs -- **/*(D) -- chown user:group --
0

Chris Down’s answer could still fail if there are a lot of files in the first directory.

find . \! -iname . -exec chown user:group {} \;

In most cases Chris Down’s answer probably won’t fail and will probably be faster than this answer, but I wanted to answer your question exactly as you asked it.

Also, here’s a slightly different command that worked better for my case. I don’t like changing directories in my scripts, so I wrote the command like this instead:

find /foo/bar/baz \! -samefile /foo/bar/baz -exec chown user:group {} \;
-1

Following is the command to change ownership of directories and its sub-dirs and all files in it recursively.

$ chown -R <username> <folder_to_change_ownership>

Step 1: Find the username by running the following command

$ whoami

this will output the username(your username will be the one you set)

manojselvin

Step 2: Copy the username from the previous step and replace in the command as follows

$ chown -R manojselvin myfolder

this command will change the ownership of all directories and sub-directories to the username mentioned. In this case it's "manojselvin"

Step 3: To check whether the ownership has been changed run the following command where the dir is located for eg. myfolder in this case.

$ ls -la

this will output the directories owner details as below

drwxr-xr-x  2 manojselvin manojselvin 4096 Jun 18 16:00 myfolder

as you can see the ownership is now "manojselvin" which is the username we used in this case. for others it will display their username or group name which has been set

  • This changes the owner of the directory itself, too. – AndreKR Jun 18 '18 at 12:36
  • yes it does @AndreKR – Manoj Selvin Jun 19 '18 at 6:43
  • It says in the question: "but not the directory itself". That's the whole point of the question. – AndreKR Jun 19 '18 at 8:30

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.