Comment puis-je faire fonctionner Chown récursivement?

285

J'ai un répertoire appelé pdfsqui contient un tas de sous-sous-répertoires et sous-répertoires. Je souhaite modifier la propriété de tous les fichiers PDF de tous les sous-dossiers. Je viens d'essayer ceci:

chown -R someuser:somegroup *.pdf

... mais cela n'a pas changé la propriété des fichiers PDF dans les sous-répertoires. L'utilisateur et le groupe existent.

Selon la page de manuel de chown, le -Rmot devrait signifier récursif:

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

Qu'est-ce que je rate?

Nathan Long
la source

Réponses:

292

Le mode récursif ne fonctionne que sur les répertoires, pas les fichiers. En utilisant le glob '* .pdf', le shell passe la liste des fichiers à chown, qui voit que ce sont des fichiers, et modifie les permissions sur les fichiers qu'il voit, et c'est tout.

Rappelez-vous que dans les shells, le glob est évalué par le shell, pas par la commande. Si le glob correspond aux fichiers, ils sont passés à la commande et celle-ci ne sait jamais qu'un glob existe. (Cela diffère de la manière dont l'invite de commande Windows faisait auparavant). Si vous avez un répertoire, avec le contenu, quelque chose comme:

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

Et vous avez tapé:

chown -R someuser:somegroup *.pdf

Le shell ferait d’abord la liste: fichier1.pdf fichier2.pdf

puis lancez votre commande:

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

Voir, il n'y a pas de répertoire pour -R sur lequel agir. Il fait ce que vous lui avez demandé - changer de propriétaire sur les deux fichiers de la ligne de commande, en ignorant cet indicateur bizarre -R.

Pour faire ce que vous voulez, utilisez le '* .pdf' comme motif pour ce répertoire et ces sous-répertoires, vous pouvez utiliser pour findrechercher les fichiers qui correspondent à un motif de nom de fichier (ou de nombreux autres critères) et les transmettre à une sous-commande

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

Cela commence dans le répertoire courant '.' pour rechercher des fichiers (type de fichier f) du modèle de nom '*.pdf'puis passe à xargs, qui construit une ligne de commande pour chmod. Notez les guillemets autour du motif '*.pdf', rappelez-vous que le shell créera un glob s'il le peut, mais que vous voulez que le motif soit transmis à find, vous devez donc le citer.

Parce que les noms de fichiers peuvent contenir des espaces, vous voulez utiliser une astuce pour le rendre sûr avec le nom de fichier avec espaces:

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

Dans bash 3 et inférieur, c'est la façon dont vous devez le faire. Un globbing plus puissant est disponible dans bash 4 (avec shopt -s globstar) et d'autres coques. Le même en zsh, en utilisant un glob récursif **:

chown -R someuser:somegroup ./**/*.pdf
Rich Homolka
la source
1
Édité pour refléter cette bash 4 avec le shopt -s globstarglobbing récursif.
Kojiro
@kojiro merci! comme vous pouvez le constater, j'utilise encore bash3
Rich Homolka
2
D'après la page de manuel affichée par l'affiche originale, j'ai trouvé que chown -R avait bien changé de propriétaire dans les dossiers ET les fichiers. Pas besoin de trouver. Utiliser la menthe 15.
gwideman
@gwideman Je sais que c'est vieux ... Mais oui, bien sûr -R est récursif. L'OP vient d'avoir un problème avec un type très spécifique de récursivité, une extension filtrée et un fichier de type "type de fichier est un fichier"
Rich Homolka
@ RichHomolka Ah. OP a déclaré que les fichiers se trouvaient dans un répertoire appelé "pdfs". J'ai donc supposé que le problème était de savoir comment spécifier pdfs en tant que répertoire à renvoyer, et que tous les fichiers contenus étaient des pdfs, il n'était donc pas nécessaire de les sélectionner spécifiquement. Mais vous avez peut-être raison, si le travail consiste à sélectionner uniquement des fichiers pdf et à ne pas modifier les autres.
Gwideman
52
chown -R someuser:somegroup /your/folder/here/*

Ceci s'appliquera à tous les fichiers et à tous les sous-répertoires et sous-sous-répertoires du dossier spécifié. Utilisez avec soin.

Sprachprofi
la source
2
D'une certaine manière, a sudo chown -R user ./fonctionné pour moi, mais sudo chown -R user ./*ne l'a pas fait
Esclave le
1
Je sais que c'est vieux, mais bien que cela réponde au titre, ne répond pas à la question. C'est en fait légèrement pire que ce que OP avait déjà essayé.
Rich Homolka
2
@RichHomolka Ayant été amené ici juste à cause du titre de la question, je suis assez heureux de trouver cette réponse.
Félix Gagnon-Grenier Le
@ FélixGagnon-Grenier assez juste. Si cette réponse fonctionne pour vous, je suis très heureux. Mais cela n'aurait pas fonctionné pour la question initiale.
Rich Homolka
Cela semble ne pas fonctionner pour les fichiers de points tels que .env.
Ryan
14

Vous pouvez utiliser l' findutilitaire:

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

S'il vous plaît ne pas oublier les citations autour *.pdf. Sinon, le shell va essayer de le développer. Cela signifie que le shell remplacera déjà *.pdfpar les noms de tous les fichiers PDF présents dans le répertoire actuel. Mais ce n'est pas ce que tu veux. Vous souhaitez rechercher les fichiers PDF situés dans des sous-répertoires. Btw .: C'est aussi le problème avec votre chowncommande.

bmk
la source
1
Je devais rechercher le bon +truc pour la performance. -exec command {} +Cette variante de l'action -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est créée en ajoutant chaque nom de fichier sélectionné à la fin. le nombre total d'invocations de la commande sera bien inférieur au nombre de fichiers correspondants. La ligne de commande est construite de la même manière que xargsses lignes de commande. Une seule instance de {}est autorisée dans la commande. La commande est exécutée dans le répertoire de départ.
Patrick M
@PatrickM un (mineur) autre avantage à + vs; .... en plus n’est pas un méta-personnage shell et ne doit pas être échappé
Rich Homolka
6

La commande

chown -R someuser:somegroup *.pdf

ne recurse que les répertoires vers le bas si le nom du répertoire se termine par .pdf. Vous avez besoin de quelque chose comme:

find . -name "*.pdf" -exec chown someuser:somegroup {} \;
Mike Scott
la source
Techniquement, cela n'aboutira qu'à un niveau inférieur. que vous appeliez cela une vraie récursion ou non est un exercice pour l'utilisateur :)
Rich Homolka
1

pour changer la propriété d'un répertoire de manière récursive, utilisez simplement:

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

here nomutilisateur = le nouvel utilisateur qui devrait être propriétaire du répertoire

nom du groupe = le nouveau groupe qui devrait être propriétaire du répertoire

chaque fichier / répertoire a un propriétaire d'utilisateur et un propriétaire de groupe

KawaiKx
la source
Cela ne fait pas ce que le PO a demandé. Cela change la propriété de tout, OP a demandé un ensemble spécifique de fichiers.
Rich Homolka
0

J'utilise à la treeplace:

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

Veillez également à ne pas exécuter récursif chown ou chmod sur le répertoire '/' ou un autre répertoire système.

Eduard Florinescu
la source
0

Pour devenir le propriétaire de tous les fichiers d’un répertoire, utilisez

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

au lieu de

sudo chown $USER directory\*

ou

sudo chown --recursive $USER directory

qui peut ne pas fonctionner s'il y a trop d'arguments produits par * (trop de fichiers dans le répertoire) ou qui ne font pas ce que vous voulez, respectivement.

masterxilo
la source