1 votos

Cómo cambiar el propietario del grupo en un directorio grande que contiene archivos bloqueados

El comando para cambiar el propietario del grupo en un directorio completo es:

chgrp -R newgroup dir_name

Por ejemplo:

chgrp -R staff .

Pero cuando dir_name contiene bloqueado archivos o directorios, este comando fallará con:

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

Si ejecuta el comando con privilegios de superusuario también fallará:

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

Si el número de archivos bloqueados es pequeño, existe una solución manual mediante el uso del comando chflags .

Compruebe que existe una bandera específica ( uchg ) asociado a un determinado archivo bloqueado:

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

Retire temporalmente el uchg bandera:

chflags nouchg file.txt

Cambiar recursivamente el grupo:

chgrp -R admin .

Restablecer el valor inicial uchg bandera:

chflags uchg file.txt

Pero este método no puede adaptarse a una enorme estructura de directorios con cientos de archivos bloqueados. Esta receta no se adapta en absoluto.


¿Cuál es el método básico y sencillo para cambiar el propietario del grupo de toda una estructura de directorios que contiene archivos bloqueados, conservando este bloqueado?

El mismo problema surge con muchos comandos para gestionar directorios que contienen archivos bloqueados, pero aquí me he centrado en un caso práctico y sencillo.

1voto

user3439894 Puntos 5883

El siguiente es un ejemplo de cómo solucionaría el problema creando un wrapper script para el chgrp comando para actuar sobre un directorio de destino teniendo problemas con archivos bloqueados .

Utilizando un bash script , llamado chgrpld le pasaría los mismos argumentos de la línea de comandos ( opciones , operando y directorio ) Lo haría si ejecutara chgrp en un directorio . Tenga en cuenta que mi convención de nomenclatura era simplemente añadir las letras ld a ella representando directorio bloqueado en el sentido de que funciona en directorios que son bloqueado o no, y o que contenga archivos/directorios que son bloqueado también. Así que donde normalmente usaría, por ejemplo, chgrp -R staff foo , donde foo es un directorio , yo usaría chgrpld -R staff foo en su lugar. El script también está codificado para funcionar en un directorio es decir no bloqueado y o no contiene objetos del sistema de archivos bloqueados también, permitiendo así el uso de chgrpld como un reemplazo regular de chgrp cuando se dirige a un directorio , si no quiero comprobar objetos del sistema de archivos bloqueados primero o tener chgrp fallar primero para luego tener que usar chgrpld de todos modos.

Nota: Este script emplea una cantidad limitada de comprobación de errores, suficiente para funcionar en condiciones de prueba limitadas. Se puede consultar en no es codificado para manejar una nueva línea incrustada en el nombre de un objeto del sistema de archivos, que, en primer lugar, no debe estar ahí. Siéntase libre de modificar como sea necesario/querido para satisfacer sus necesidades, añadiendo una comprobación de errores adicional si/cuando se quiera/necesite.

El entorno de prueba fue OS X 10.11.5 en un directorio como se muestra en el siguiente listado, teniendo dos directorios Cada uno de ellos con una archivo en él y uno de los archivos bloqueado. Un conjunto de directorios/archivos está en el admin grupo y el otro set está en el staff grupo y quiero que todo esté en el staff grupo . (Véase la nota de la prueba al final de la respuesta para obtener información adicional sobre la prueba).

La salida del terminal muestra:

  • Una recursividad directorio de la lista.
  • Un intento de utilizar chgrp mostrando su salida de error.
  • Utilizando chgrpld ejecutándose sin error.
  • Otra recursividad directorio para mostrar el grupo ha cambiado.

$ 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
$ 

Para crear el chgrpld bash script y tenerlo disponible en el indicador de comandos :

En la terminal:

  • Tipo, touch chgrpld y pulse enter .
  • Tipo, open chgrpld y pulse enter .

Desde el navegador:

  • Copiar y pegar, el código abajo en el abierto chgrpld y guárdelo, luego cierre el archivo.

De vuelta a la terminal:

  • Tipo, chmod +x chgrpld y pulse enter .
  • Tipo, sudo mkdir -p /usr/local/bin y pulse enter . Tenga en cuenta que en una instalación limpia de OS X 10.11.5, el bin directorio en /usr/local no existía aunque ya está en el PATH .
    • Escriba contraseña y pulse enter .
  • Tipo sudo cp chgrpld /usr/local/bin y pulse enter .
    • Escriba contraseña y pulse enter . (Si es necesario.)
  • chgrpld debería estar ahora disponible para su uso, al igual que el chgrp comando .

Fuente código para 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

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

  • Ver man chgrp en Terminal para la descripción de opciones y group operando .

  • directory es el nombre/patrón del objetivo directorio es decir bloqueado o no, y o que contenga archivos/directorios que son bloqueado también. Tenga en cuenta que, a diferencia de chgrp lo que permite múltiples objetos Por ejemplo group file ... para actuar, chgrpld está codificado para actuar sobre un objetivo directorio y recursivamente con el -R opción a la vez.

  • Nota: El usuario que invoca chgrpld debe pertenecer al grupo y ser el propietario de la directorio y objetos del sistema de archivos bloqueados o ser el superusuario .

  • Como es de esperar en las versiones SIP del sistema operativo, esto no funcionará en las versiones protegidas por SIP objetos del sistema de archivos si el SIP está activado.


La siguiente imagen muestra el resaltado sintáctico del código con comentarios espaciados y sangrados para facilitar la lectura y ayudar a explicar un poco lo que el código está haciendo.

Image of Code


Nota de prueba: Aunque el entorno de prueba mostrado arriba es limitado, lo probé bajo una estructura jerárquica de directorios más compleja, con muchos más directorios y archivos anidados y bloqueados, con nombres que contienen espacios o barras invertidas dentro del nombre del archivo, sin problemas. Obviamente, para fines de demostración, sólo estoy mostrando una estructura mínima para probar el concepto. Una vez más, como se señaló anteriormente, " Es no es codificado para manejar una nueva línea incrustada en el nombre de un objeto del sistema de archivos, que, en primer lugar, no debe estar ahí. ".

0 votos

Código sencillo y limpio. Agradable para la advertencia de limitación sobre las nuevas líneas ;).

0 votos

¿Qué pasa si un "archivo" tiene varias banderas como hidden,uchg o schg,uchg ? Buen comentario en tu script.

0 votos

@fd0, permíteme empezar diciendo que ya he dicho " El siguiente es un ejemplo de cómo solucionaría el problema " que cubre el escenario de que el objeto del sistema de archivos esté bloqueado y " Siéntase libre de modificar lo que necesite o desee para satisfacer sus necesidades " que cubre el hecho de estar encerrado y escondido al mismo tiempo. Lo que he presentado es un ejemplo de una envoltura de trabajo script para ser utilizado como una plantilla. Sí, añadiendo una comprobación y manejo de uchg,hidden Las banderas son fáciles de hacer, si se quiere. Gracias por el complemento en el comentario de código, me gustaría mirar hacia atrás en 6 meses y saber qué y por qué lo escribí de esa manera. :)

0voto

Rich Puntos 2429

Solución de 2 conchas

Finalmente después de muchos intentos construí una solución de 2 cortos shell scripts.

Uno bastante básico que hará el:

chflags, chgrp, chflags

Uno más serio que hará el recorrido de la estructura de directorios:

find ... do the chgrp correctly

Small shell: chflags, chgrp, chflags

Este es el contenido de chgrpld1.sh que normalmente funcionará llamado desde find con exactamente 2 argumentos.

#!/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 ... hacer el chgrp correctamente

Este es el contenido de chgrpld.sh que ejecutará una búsqueda en el directorio y evitar en lo posible las condiciones de error por adelantado.

#!/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} "{}" \; \)

Instalar

Para que estas dos carcasas funcionen juntas, es necesario instalar ambos en un directorio local que esté en el PATH . En mi caso utilizo /local/bin para permanecer fuera de los componentes del PATH del sistema, y fuera de los utilizados por los gestores de paquetes ( port , brew ).

Copie los 2 archivos precedentes en el directorio elegido:

chgrpld1.sh
chgrpld.sh

make chgrpld1 chgrpld

cp chgrpld1 chgrpld /local/bin

Prueba

Para validar que este shell se ejecuta correctamente en todos los casos, hice un directorio de prueba de prueba con todas las combinaciones de banderas que se pueden encontrar con todos los nombres de archivos imposibles con los que debería lidiar sin un error.

dir-ok es el subdirectorio que contiene los horrores en los que mi script debería tener éxito, dir-fail es la que contiene todos los casos en los que debe fallar:

% 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
  • Sigue 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
    $
  • Sigue 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
    $

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X