1 votes

Comment changer le propriétaire d'un groupe dans un grand répertoire contenant des fichiers verrouillés ?

La commande pour changer le propriétaire d'un groupe dans un répertoire entier est la suivante :

chgrp -R newgroup dir_name

Par exemple :

chgrp -R staff .

Mais quand dir_name contient verrouillé ou des répertoires, cette commande échouera avec :

chgrp -R staff .
chgrp: ./file.txt: Operation not permitted

Si vous exécutez la commande avec les privilèges d'un super utilisateur, elle échouera également :

/usr/bin/sudo chgrp -R staff .
Password:
chgrp: ./file.txt: Operation not permitted

Si le nombre de fichiers verrouillés est faible, il existe une solution de contournement manuelle en utilisant la commande chflags .

Vérifier qu'il existe un drapeau spécifique ( uchg ) associée à un fichier verrouillé donné :

ls -@delO file.txt 
-rw-r--r--  1 bob  staff  uchg 32 Aug  8 11:38 file.txt

Retirer temporairement le uchg drapeau :

chflags nouchg file.txt

Modifier récursivement le groupe :

chgrp -R admin .

Remise à zéro de la valeur initiale uchg drapeau :

chflags uchg file.txt

Mais cette méthode ne peut pas s'adapter à une énorme structure de répertoires comportant des centaines d'éléments. de fichiers verrouillés. Cette méthode n'est pas du tout adaptée.


Quelle est la méthode simple de base pour changer le groupe propriétaire d'une structure de répertoire entière contenant des fichiers verrouillés, tout en préservant ce statut verrouillé ? verrouillé ?

Le même problème se pose avec de nombreuses commandes de gestion des répertoires contenant des fichiers verrouillés, mais je me suis concentré ici sur une solution pratique. pratique et simple.

1voto

user3439894 Points 52496

Voici un exemple de la manière dont je contournerais le problème en créant un fichier wrapper script pour les chgrp commande agir sur une répertoire cible ayant des problèmes avec fichiers verrouillés .

L'utilisation d'un bash script , nommé chgrpld je lui transmettrais les mêmes arguments de ligne de commande ( options , opérande y répertoire ) Je le ferais si l'exécution chgrp sur un répertoire . Notez que ma convention de dénomination consistait simplement à ajouter les lettres ld qui représente répertoire verrouillé En effet, il fonctionne sur répertoires qui sont verrouillé ou non, et ou contenant fichiers/répertoires qui sont verrouillé trop. Ainsi, là où j'utiliserais normalement, par exemple, chgrp -R staff foo donde foo est un répertoire J'utiliserais chgrpld -R staff foo au lieu de cela. Les script est également codé pour fonctionner sur un répertoire c'est-à-dire non verrouillé et ou ne contient pas objets du système de fichiers verrouillés également, ce qui permet l'utilisation de chgrpld en remplacement régulier de chgrp lorsqu'il s'agit de cibler un répertoire Si je ne veux pas vérifier la présence de objets du système de fichiers verrouillés d'abord ou avoir chgrp échoue d'abord pour devoir ensuite utiliser chgrpld Quoi qu'il en soit.

Note : Cette script utilise un nombre limité de contrôles d'erreurs, suffisant pour fonctionner dans des conditions de test limitées. Il s'agit d'un contrôle d'erreur limité, suffisant pour fonctionner dans des conditions de test limitées. n'est pas codé pour gérer une nouvelle ligne intégrée dans le nom d'un objet du système de fichiers, qui IMO n'a pas sa place en premier lieu ! N'hésitez pas à modifier ce code pour l'adapter à vos besoins, en ajoutant des contrôles d'erreur supplémentaires si nécessaire.

L'environnement de test était OS X 10.11.5 dans un local temporaire. répertoire comme le montre la liste ci-dessous, avec deux répertoires , chacun avec un fichier en son sein et l'un des dossiers verrouillé. Un seul ensemble de répertoires/fichiers est dans la admin groupe et l'autre fixer est dans la staff groupe et je veux que tout soit dans la staff groupe . (Voir la note sur les tests à la fin de la réponse pour des informations supplémentaires sur les tests).

La sortie du terminal montre :

  • Un système récursif répertoire liste.
  • Une tentative d'utiliser chgrp en affichant sa sortie d'erreur.
  • Utilisation chgrpld s'exécutant sans erreur.
  • Une autre méthode récursive répertoire pour montrer le groupe a changé.

$ ls -lRO
total 0
drwxr-xr-x  3 user  staff  - 102 Aug  9 2:00 bar
drwxr-xr-x  3 user  admin  - 102 Aug  9 2:00 foo

./bar:
total 0
-rw-r--r--  1 user  staff  - 0 Aug  9 2:00 foo

./foo:
total 0
-rw-r--r--  1 user  admin  uchg 0 Aug  9 2:00 bar
$ chgrp -R staff foo
chgrp: foo/bar: Operation not permitted
$ chgrpld -R staff foo
$ ls -lRO
total 0
drwxr-xr-x  3 user  staff  - 102 Aug  9 2:00 bar
drwxr-xr-x  3 user  staff  - 102 Aug  9 2:00 foo

./bar:
total 0
-rw-r--r--  1 user  staff  - 0 Aug  9 2:00 foo

./foo:
total 0
-rw-r--r--  1 user  staff  uchg 0 Aug  9 2:00 bar
$ 

Pour créer le chgrpld bash script et le mettre à disposition au invite de commande :

En terminal :

  • Type, touch chgrpld et appuyez sur enter .
  • Type, open chgrpld et appuyez sur enter .

Depuis le navigateur :

  • Copier-coller, le code ci-dessous dans l'espace ouvert chgrpld et l'enregistrer, puis fermer le fichier.

Retour au terminal :

  • Type, chmod +x chgrpld et appuyez sur enter .
  • Type, sudo mkdir -p /usr/local/bin et appuyez sur enter . Notez que sur une installation propre de OS X 10.11.5, l'option bin à l'adresse /usr/local n'existait pas alors qu'il est déjà dans le fichier PATH .
    • Type dans mot de passe et appuyez sur enter .
  • Type sudo cp chgrpld /usr/local/bin et appuyez sur enter .
    • Type dans mot de passe et appuyez sur enter . (si nécessaire).
  • chgrpld devrait maintenant être disponible, tout comme la fonction chgrp commande .

Source code pour chgrpld :

#!/bin/bash

o="${@:1:$(($#-1))}"
d="${@: -1}"
if [ -d "$d" ]; then
    f=".locked_files_list_$(date "+%s")"
    find "$d" -flags uchg > "$f" 2>/dev/null
    if [ -s "$f" ]; then
        while read -r l; do
            chflags nouchg "$l"
        done<"$f"
            $(chgrp $o "$d")
        while read -r l; do
            chflags uchg "$l"
        done<"$f"
        rm "$f"
    else
        rm "$f"
        $(chgrp $o "$d")
    fi
else
    echo "  \"$d\" is not a directory!..."
    exit 1
fi
exit 0

Synopsis : chgrpld [fhv][R[H | L | P]] group directory

  • Voir man chgrp dans le terminal pour la description de la options y group opérande .

  • directory est le nom/nom de famille de la cible répertoire c'est-à-dire verrouillé ou non, et ou contenant fichiers/répertoires qui sont verrouillé aussi. Il convient de noter que, contrairement aux chgrp qui permet à plusieurs objets , par exemple group file ... d'agir, chgrpld est codé pour agir sur une cible répertoire et de manière récursive avec le -R option à la fois.

  • Note : L'utilisateur qui invoque chgrpld doit appartenir à la catégorie groupe et être le propriétaire de la répertoire y objets du système de fichiers verrouillés ou être le super-utilisateur .

  • Comme prévu dans les versions SIP du système d'exploitation, cela ne fonctionnera pas si le système est protégé par SIP. objets du système de fichiers si SIP est activé.


L'image ci-dessous montre la mise en évidence syntaxique de l'élément code avec des commentaires espacés et indentés pour faciliter la lecture et expliquer un peu ce qu'est la code est en train de faire.

Image of Code


Note de test : Bien que l'environnement de test présenté ci-dessus soit limité, je l'ai néanmoins testé dans une structure de répertoires hiérarchique plus complexe, avec beaucoup plus de répertoires et de fichiers imbriqués verrouillés, avec des noms contenant des espaces ou des barres obliques inverses dans le nom du fichier, sans aucun problème. Évidemment, à des fins de démonstration, je ne montre qu'une structure minimale pour prouver le concept. Encore une fois, comme indiqué ci-dessus, " Il n'est pas codé pour gérer une nouvelle ligne intégrée dans le nom d'un objet du système de fichiers, qui n'a pas sa place en premier lieu ! ".

0voto

Rich Points 2429

Solution à 2 coquilles

Finalement, après de nombreuses tentatives, j'ai mis au point une solution à deux courts scripts scripts.

L'un d'entre eux, assez basique, fera l'affaire :

chflags, chgrp, chflags

Une autre, plus sérieuse, qui se chargera de parcourir la structure des répertoires :

find ... do the chgrp correctly

Petit shell : chflags, chgrp, chflags

Voici le contenu de chgrpld1.sh qui fonctionnera généralement sous le nom de à partir de find avec exactement 2 arguments.

#!/bin/sh
# shell script to chgrp a file or directory
# when there exists a lock flags (uchg)

_cn=`basename $0`

USAGE="Usage: ${_cn} group file"

case $# in
2)
        _group=$1
        _file="$2"
        ;;
*)
        echo "$USAGE" >&2
        exit 2
        ;;
esac

chflags nouchg "${_file}"
chgrp ${_group} "${_file}"
chflags uchg "${_file}"

Big shell : find ... faire le chgrp correctement

Voici le contenu de chgrpld.sh qui lancera une recherche dans le répertoire et éviter autant que possible les conditions d'erreur à l'avance.

#!/bin/sh
# shell script to recursively chgrp a file or directory
# when there exists files which are locked

_cn=`basename $0`

USAGE="Usage: ${_cn} group file..."

case $# in
0|1)
        echo "$USAGE" >&2
        exit 2
        ;;
*)
        _group=$1
        shift
        _file_list="$@"
        ;;
esac

TMPDIR=/tmp
_file_flags_list=`mktemp -t ${_cn}`

clean() { rm -f ${_file_flags_list} ; }

trap clean 0 1 2 3

# first check if we don't have any sort of flags thus blocking this
# script

find "${_file_list}" -flags +sappnd,schg,uappend -exec ls -@delO "{}" \; >${_file_flags_list}

if [ -s ${_file_flags_list} ] ; then
        echo "${_cn}: can't run because of other flags set:"
        cat ${_file_flags_list}
        exit 1
fi

# if flag present then call chgrpld1, else plain chgrp

find "${_file_list}" \( -flags uchg -exec chgrpld1 ${_group} "{}" \; \) -or \( -exec chgrp ${_group} "{}" \; \)

Installer

Pour faire fonctionner ces 2 shells ensemble, il est nécessaire d'installer les deux dans un répertoire local qui se trouve dans le répertoire PATH . Dans mon cas, j'utilise /local/bin pour rester en dehors des composants PATH du système, et en dehors de ceux utilisés par les gestionnaires de paquets ( port , brew ).

Copier les 2 fichiers précédents dans le répertoire choisi :

chgrpld1.sh
chgrpld.sh

make chgrpld1 chgrpld

cp chgrpld1 chgrpld /local/bin

Test

Pour valider que ce shell fonctionne correctement dans tous les cas, j'ai fait un test peuplé de toutes les combinaisons de drapeaux que l'on peut rencontrer avec tous les noms de fichiers impossibles qu'il devrait pouvoir traiter sans erreur.

dir-ok est le sous-répertoire contenant les horreurs sur lesquelles mon script a été créé. devrait réussir, dir-fail est celui qui contient tous les cas sur lesquels il devrait échouer :

% ls -blOR
total 0
drwxr-xr-x  2 bob  admin          - 204 Aug 16 16:50 dir-fail
drwxr-xr-x  3 bob  localaccounts  - 238 Aug 16 16:55 dir-ok

./dir-fail:
total 0
-rw-r--r--  1 bob  admin  schg,uchg 0 Aug  9 18:59 file-multi-flags
-rw-r--r--  1 bob  admin  sappnd    0 Aug 16 16:13 file-sappnd
-rw-r--r--  1 bob  admin  schg      0 Aug 16 16:11 file-schg
-rw-r--r--  1 bob  admin  uappnd    0 Aug 16 16:12 file-uappend

./dir-ok:
total 0
-rw-r--r--  1 bob  localaccounts  -      0 Aug 16 16:07 a\nb
-rw-r--r--  1 bob  localaccounts  -      0 Aug  9 19:34 a b
-rw-r--r--  1 bob  localaccounts  -      0 Aug  9 19:34 a'b
-rw-r--r--  1 bob  localaccounts  -      0 Aug 16 16:46 a\\b
drwxr-xr-x  2 bob  localaccounts  uchg 272 Aug 16 16:39 subdir

./dir-ok/subdir:
total 0
-rw-r--r--  1 bob  localaccounts  -      0 Aug 16 16:08 file
-rw-r--r--  1 bob  localaccounts  arch   0 Aug 16 16:12 file-arch
-rw-r--r--@ 1 bob  localaccounts  hidden 0 Aug 16 16:10 file-hidden
-rw-r--r--  1 bob  localaccounts  nodump 0 Aug 16 16:11 file-nodump
-rw-r--r--  1 bob  localaccounts  opaque 0 Aug 16 16:10 file-opaque
-rw-r--r--  1 bob  localaccounts  uchg   0 Aug 16 16:08 file-uchg
  • Continuer à courir dir-ok

    $ chgrpld staff dir-ok
    $ ls -blOR dir-ok
    total 0
    -rw-r--r--  1 bob  staff  -      0 Aug 16 16:07 a\nb
    -rw-r--r--  1 bob  staff  -      0 Aug  9 19:34 a b
    -rw-r--r--  1 bob  staff  -      0 Aug  9 19:34 a'b
    -rw-r--r--  1 bob  staff  -      0 Aug 16 16:46 a\\b
    drwxr-xr-x  2 bob  staff  uchg 272 Aug 16 16:39 subdir
    
    dir-ok/subdir:
    total 0
    -rw-r--r--  1 bob  staff  -      0 Aug 16 16:08 file
    -rw-r--r--  1 bob  staff  arch   0 Aug 16 16:12 file-arch
    -rw-r--r--@ 1 bob  staff  hidden 0 Aug 16 16:10 file-hidden
    -rw-r--r--  1 bob  staff  nodump 0 Aug 16 16:11 file-nodump
    -rw-r--r--  1 bob  staff  opaque 0 Aug 16 16:10 file-opaque
    -rw-r--r--  1 bob  staff  uchg   0 Aug 16 16:08 file-uchg
    $
  • Continuer à courir dir-fail

    $ chgrpld staff dir-fail/file-multi-flags 
    chgrpld: can't run because of other flags set:
    -rw-r--r--  1 bob  admin  schg,uchg 0 Aug  9 18:59 dir-fail/file-multi-flags
    
    $ chgrpld staff dir-fail/file-sappnd      
    chgrpld: can't run because of other flags set:
    -rw-r--r--  1 bob  admin  sappnd 0 Aug 16 16:13 dir-fail/file-sappnd
    
    $ chgrpld staff dir-fail/file-schg  
    chgrpld: can't run because of other flags set:
    -rw-r--r--  1 bob  admin  schg 0 Aug 16 16:11 dir-fail/file-schg
    
    $ chgrpld staff dir-fail/file-uappend
    chgrpld: can't run because of other flags set:
    -rw-r--r--  1 bob  admin  uappnd 0 Aug 16 16:12 dir-fail/file-uappend
    $

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X