[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Rechte übertragen



Hallo,
[ich faß mal beide Antworten zusammen]

Am Thu, 08 May 2014, Stefan Baur schrieb:
>Am 07.05.2014 21:04, schrieb David Haller:
>> # find ../kranke_namen/ -mindepth 1 -printf '%U:%G\0%P\0' | \
>                                       ^^^^^^^^^^^^^^^^^^^^
>Was macht das, was -print0 nicht macht?
>
>Normalerweise, wenn man ein xargs mit -0 aufruft und von find füttern
>lässt, verwendet man doch -print0 bei find.

Schau nochmal genau hin (bevor du unten spickst) ;)

Am Thu, 08 May 2014, Andre Tann schrieb:
>schön mal wieder von Dir zu lesen.

[1]

>Am 07.05.2014 21:04, schrieb David Haller:
>
>> # find ../kranke_namen/ -mindepth 1 -printf '%U:%G\0%P\0' | \
>>     xargs -r0 -n 2 chown -c
>> changed ownership of `foo *" \'\n bar*' from dh:dh to 0:1024
>> changed ownership of `foo *" \' bar*' from dh:dh to 501:1024
>> changed ownership of `foo" \' bar' from dh:dh to 399:1024
>
>Wozu -r0? Da steht bei mir in der man-page gar nicht dokumentiert. Das
>hast Du für den Fall, daß find gar nichts findet, richtig?
>
>...ach, jetzt hab ichs auch... -r -0. OK, paßt.

Korrekt.

>-n2 - Welchen Fall fängst Du damit ab?
>
>Wie immer - merci für den Trick!

Das -n 2 macht aus den 2 Argumenten

%U:%G       (also UID:GID)
%P          (relativer PFAD ohne Fundort)

die durch \0 getrennt sind _einen_ Aufruf für's chown.

Das -printf schreibt ja eine Liste wie

UID1:GID1\0NAME1\0UID2:GID2\0NAME2\0... in die Pipe.

Das xargs -0 -n 2 macht aus je 2 Argumenten je einen Aufruf von chown:

chown -c UID1:GID1 NAME1
chown -c UID2:GID2 NAME2

wobei chown eben die Namen absolut korrekt per 'execve' in argv
übergeben bekommt, ohne daß da eine Shell nochmal was expandieren oder
splitten könnte. Hier mal ein "lesbar" gemachtes strace:

# find  /tmp/kranke_dateinamen/ -mindepth 1 -printf '%U:%G\0%P\0'| \
    PATH=/bin:/usr/bin strace -f -eprocess xargs  -r0 -n 2 chown -c

execve("/usr/bin/xargs", ["xargs", "-r0", "-n", "2", "chown", "-c"],
clone(Process 3331 attached
[pid  3331] execve("/bin/chown", ["chown", "-c", "500:1024", "foo *\" ' bar*"],
clone(Process 3332 attached
[pid  3332] execve("/bin/chown", ["chown", "-c", "500:1024", "foo\" ' bar"],
[..]

Das ganze ist zwar sehr ineffektiv, weil für jede Datei/jedes
Verzeichnis ein extra 'chown' aufgerufen wird. Andererseits ist es mit
shell-Möglichkeiten kaum anders möglich, da ja jede Datei andere
Rechte haben kann. Eine Alternative wäre perl.

Ah, jetzt ja. Könnte man noch darauf optimieren, daß perl's chown
mehrere Dateien gleichzeitig verwursten kann, aber ich glaube nicht,
daß sich der Aufwand lohnt.

==== find_and_dup_owner.pl [MINIMAL GETESTET!] ====
#!/usr/bin/perl -w
use strict;
use File::Find;

usage(0) if grep { /^-h$|^--h/ } @ARGV;
usage(1) unless scalar @ARGV == 2;

my($fromdir, $todir) = @ARGV;
$fromdir =~ s{/$}{};
$todir =~ s{/$}{};

sub usage {
    print STDERR "USAGE: $0 FROMDIR TODIR\n";
    exit $_[0];
}

sub do_chown {
    return if $_ eq $fromdir;
    my $newf = $File::Find::name;
    $newf =~ s{^$fromdir/}{$todir/};
    if ( -e $newf ) {
        my @ref = stat($File::Find::name);
        my @old = stat($newf);
        chown($ref[4], $ref[5], $newf);
        my @new = stat($newf);
        printf STDERR "chown'ed from %s:%s to %s:%s: `%s'\n",
          $old[4], $old[5], $new[4], $new[5], $newf;
    }
}

finddepth( { wanted => \&do_chown,
             no_chdir => 1,
           },
           $fromdir
         );
1;
====

$ ~/bin/find_and_dup_owner.pl ~/kranke_dateinamen/ /tmp/dh/
chown'ed from 500:100 to 500:1024: `/tmp/dh/foo *" ' bar*'
chown'ed from 500:100 to 500:1024: `/tmp/dh/foo" ' bar'
chown'ed from 500:100 to 500:1024: `/tmp/dh/foo *" '
 bar*'
chown'ed from 500:100 to 500:1024: `/tmp/dh/more/foo *" ' bar*'
[..]

HTH,
-dnh

[1] auf dieser Liste lese ich eben nur sporadisch ...

-- 
Die ultimativen Man-Pages haben ein ".c" als Dateiendung.
                                    -- am DLUG-Stammtisch


Reply to: