¿Cómo puedo hacer que chown funcione recursivamente?

283

Tengo un directorio llamado pdfsque contiene un montón de subdirectorios y subdirectorios. Quiero cambiar la propiedad de todos los archivos PDF en todas las subcarpetas. Acabo de intentar esto:

chown -R someuser:somegroup *.pdf

... pero no cambió la propiedad de los PDF en subdirectorios. El usuario y el grupo existen.

De acuerdo con la página del manual para chown, el -Rdebería significar recursivo:

-R, --recursive
          operate on files and directories recursively

¿Qué me estoy perdiendo?

Nathan Long
fuente

Respuestas:

289

El modo recursivo solo funciona en directorios, no en archivos. Al usar el glob '* .pdf', el shell pasa la lista de archivos a chown, que ve que son archivos y cambia los permisos en los archivos que ve, y eso es todo.

Recuerde, en shells, el glob es evaluado por el shell, no por el comando. Si el glob coincide con los archivos, se pasan al comando y el comando nunca sabe que existe un glob. (Esto es diferente de cómo el símbolo del sistema de Windows solía hacer cosas). Si tiene un directorio, con los contenidos algo así como:

machine:$ ls -F
file1.pdf  file2.pdf  other.txt  subdir/

Y escribiste:

chown -R someuser:somegroup *.pdf

El shell primero haría la lista: file1.pdf file2.pdf

y luego ejecuta tu comando:

chown -R someuser:somegroup file1.pdf file2.pdf

Mira, no hay un directorio para que -R actúe. Hace lo que le pediste: cambiar la propiedad de los dos archivos en la línea de comando, ignorando esa peculiar bandera -R.

Para hacer lo que quiera, para usar el '* .pdf' como patrón para este directorio y subdirectorios, puede usar find, que puede encontrar archivos que coincidan con un patrón de nombre de archivo (o muchos otros criterios) y pasar a un subcomando

find . -type f -name '*.pdf' | xargs chown someuser:somegroup

Esto comienza en el directorio actual '.' para buscar archivos (tipo de archivo f) del patrón de nombre '*.pdf'luego pasa a xargs, que construye una línea de comando para chmod. Observe las comillas alrededor del patrón '*.pdf', recuerde que el shell creará un globo si puede, pero desea que se pase el patrón find, por lo que debe citarlo.

Debido a que los nombres de archivo pueden tener espacios, debe usar un truco para que sea seguro para nombre de archivo con espacios:

find . -type f -name '*.pdf' -print0 | xargs -0 chown someuser:somegroup

En bash 3 y versiones inferiores, esta es la forma en que debe hacerlo. Se dispone de un engrosamiento más potente en bash 4 (con shopt -s globstar) y otros proyectiles. Lo mismo en zsh, usando un globo recursivo **:

chown -R someuser:somegroup ./**/*.pdf
Rich Homolka
fuente
1
Editado para reflejar que bash 4 con shopt -s globstarhace recursive globbing.
kojiro
@kojiro gracias! como pueden ver, todavía uso bash3
Rich Homolka
2
De acuerdo con la página de manual que se muestra en el póster original, encontré que el chown -R realmente cambió el propietario de las carpetas Y archivos. No hay necesidad de encontrar. Usando Mint 15.
gwideman
@gwideman Sé que esto es viejo ... Pero sí, por supuesto -R es recursivo. El OP acaba de tener un problema con un tipo de recursión muy específico, una extensión y "tipo de archivo es un archivo" filtrado
Rich Homolka
@RichHomolka Ah. OP dijo que los archivos estaban en un directorio llamado 'pdf', por lo que supuse que el problema estaba en cómo especificar los archivos PDF como el directorio que se repetirá, y que todos los archivos contenidos eran archivos PDF, por lo que no es necesario seleccionarlos específicamente. Pero es posible que tenga razón, si el trabajo es seleccionar solo archivos PDF y dejar los demás sin cambios.
gwideman
51
chown -R someuser:somegroup /your/folder/here/*

Esto aplicará chown a todos los archivos y todos los subdirectorios y subdirectorios de la carpeta especificada. Usar con cuidado.

Sprachprofi
fuente
2
De alguna manera sudo chown -R user ./funcionó para mí, pero sudo chown -R user ./*no lo hizo
Slav
1
Sé que esto es viejo, pero aunque esto responde al titular, no responde la pregunta. Esto es en realidad un poco peor de lo que OP ya había intentado.
Rich Homolka
2
@RichHomolka Habiendo sido traída aquí solo por el título de la pregunta, estoy muy feliz de encontrar esta respuesta.
Félix Gagnon-Grenier
@ FélixGagnon-Grenier bastante justo. Si esta respuesta funciona para ti, estoy muy feliz. Pero no habría funcionado para la pregunta original.
Rich Homolka
Esto parece no funcionar para archivos de puntos como .env.
Ryan
14

Puedes usar la findutilidad:

find . -name '*.pdf' -exec chown someuser:somegroup {} +

Por favor, no olvide las citas alrededor *.pdf. De lo contrario, el shell intentará expandirlo. Esto significa que el shell ya se reemplazará *.pdfcon los nombres de todos los archivos PDF encontrados en el directorio actual. Pero eso no es lo que quieres. Desea encontrar los archivos PDF ubicados en subdirectorios. Por cierto: Ese también es el problema con su chowncomando.

bmk
fuente
1
Tuve que buscar el +truco ordenado para el rendimiento. -exec command {} +Esta variante de la acción -exec ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se crea agregando cada nombre de archivo seleccionado al final; El número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando se construye de la misma manera que xargsconstruye sus líneas de comando. Solo {}se permite una instancia de dentro del comando. El comando se ejecuta en el directorio de inicio.
Patrick M
@PatrickM una (menor) otra ventaja para + vs; .... además no es un meta personaje de shell y no tiene que escapar
Rich Homolka
6

El comando

chown -R someuser:somegroup *.pdf

solo repetirá directorios si el nombre del directorio termina en .pdf. Necesitas algo como:

find . -name "*.pdf" -exec chown someuser:somegroup {} \;
Mike Scott
fuente
Técnicamente solo irá a un nivel por debajo. si llama a eso verdadera recursión o no es un ejercicio para el usuario :)
Rich Homolka
1

para cambiar la propiedad de un directorio de forma recursiva simplemente use:

sudo chown -R <username>:<groupname> <dir name>

aquí nombre de usuario = el nuevo usuario que debería ser propietario del directorio

groupname = el nuevo grupo que debería ser propietario del directorio

cada archivo / directorio tiene un propietario de usuario y un propietario de grupo

KawaiKx
fuente
Esto no hace lo que pidió el OP. Esto cambia la propiedad de todo, OP solicitó un conjunto específico de archivos.
Rich Homolka
0

Yo uso treeen su lugar:

 sudo tree -fai ~/.blabla  | xargs -L1 -I{} sudo chown youruser:youruser {}

También tenga cuidado de no ejecutar chown recurrente o chmod en el directorio '/' u otro directorio del sistema.

Eduard Florinescu
fuente
0

Para convertirse en el propietario de todos los archivos en un directorio, use

find directory -type f -name '*' | sudo xargs -d '\n' chown $USER

en vez de

sudo chown $USER directory\*

o

sudo chown --recursive $USER directory

que podría no funcionar si hay demasiados argumentos producidos por * (demasiados archivos en el directorio) o que no hace lo que desea, respectivamente.

masterxilo
fuente