Groups | Search | Server Info | Keyboard shortcuts | Login | Register


Groups > de.comp.os.unix.shell > #14606

Re: Gruppierung mit uniq für NUL-getrennte Daten?

From Helmut Waitzmann <nn.throttle@xoxy.net>
Newsgroups de.comp.os.unix.shell
Subject Re: Gruppierung mit uniq für NUL-getrennte Daten?
Date 2025-10-12 22:57 +0200
Organization A noiseless patient Spider
Message-ID <83ecr7et3g.fsf@helmutwaitzmann.news.arcor.de> (permalink)
References <87h5w4nr3u.fsf@vagabond.tim-landscheidt.de>

Show all headers | View raw


 Tim Landscheidt <tim@tim-landscheidt.de>:
> ich möchte mit (GNU) find

 (also nehme ich an, dass der GNU‐Werkzeugkoffer zur Verfügung 
 steht) 


> eine Liste von Dateien erstellen und abarbeiten, aber
> hardverlinkte Dateien nur einmal, sprich: Einmal pro Inode.
>
> Die Liste kann ich mit „find -printf '%i\0%p\0'“ erzeugen.
> Aber wie bekomme ich mit uniq oder anderen GNU/Linux-Bord-
> mitteln eine Gruppierung (in diesem Fall nur den ersten
> Treffer) nach Inode hin, wenn ich bei den Dateinamen belie-
> bige Zeichen erwarte?
>
> Die Pipeline:
>
> | find -type f -printf '%8i\t%p\0' | uniq -zw 8 | cut -zc10- | […]
>
> funktioniert, ist aber hässlich (und falsch, da Inodes wohl
> 64 Bit haben können, und man deshalb mit 20 Ziffern rechnen
> muss

 Was empfindest du daran als hässlich?  Ich kann jetzt auf die 
 Schnelle (abgesehen davon, dass zwischen „find“ und „uniq“ noch 


    sort --zero-terminated


 gehört) nichts Hässliches entdecken. 


 Eine andere Möglichkeit, die die Gruppierung ohne vollständiges 
 Sortieren hinbekommt, aber dafür die Fähigkeiten des Dateisystems 
 nutzt, könnte so aussehen: 


   find . -type f -printf '%i %p\0' |
   xargs -0 -r -- sh -c '
     exit_status=: &&
     for nummer_name
     do
       if ! \
         {
           nummer="${nummer_name%% *}" &&
           name="${nummer_name#* }" &&
           link=../nummer/"$nummer" &&
           if ! test -e "$link"
           then
             ln -- "$name" "$link"
           fi
         }
       then
         exit_status=false
       fi
     done
     "$exit_status"' sh &&


 Hier wird im Verzeichnis „../nummer/“ zu jedem gefundenen Inode 
 ein (weiteres) Hardlink (mit der Inode‐Nummer als Name) 
 angelegt.  (An die originalen Dateinamen kommt man so aber nicht 
 direkt ran.) 


 Ich würde wahrscheinlich im Allgemeinen deine Lösung (ergänzt 
 durch „sort“) vorziehen, weil sie ohne viele Manipulationen 
 (hier: ein Hardlink anlegen) an den zu gruppierenden Dateien 
 auskommt.  Nur im Fall, dass das Sortieren die Maschine in die 
 Knie zwingt (weil es sehr viele Dateien sind) oder anderweitig 
 unerwünscht ist, würde ich Alternativen betrachten. 


 Statt im Verzeichnis „../nummer/“ Hardlinks anzulegen, könnte man 
 dort auch Dateien, in denen jeweils die gefundenen originalen 
 Dateinamen (mit ASCII NUL von einander getrennt) stehen, 
 ablegen.  Dann muss der „sh“‐Aufruf oben so aussehen: 


   xargs -0 -r -- sh -c '
     exit_status=: &&
     for nummer_name
     do
       if ! \
         {
           nummer="${nummer_name%% *}" &&
           name="${nummer_name#* }" &&
           names=../nummer/"$nummer" &&
           printf %s\\0 "$name" >> "$names"
         }
       then
         exit_status=false
       fi
     done
     "$exit_status"' sh


 Das ergibt einen Katalog aller Dateinamen, nach Inode‐Nummern 
 gruppiert. 


 Vorteile:  Die originalen Dateien bleiben unangetastet:  Es ist 
 keine Erzeugung eines weiteren Hardlinks nötig, daher geschieht 
 keine Änderung des Zeitstempels der letzten Inode‐Änderung.  Auch 
 kann der Fall, dass das Anlegen eines Hardlinks scheitert, weil 
 das Inode bereits die maximale Anzahl von Hardlink erreicht hat, 
 nicht eintreten. 


 Wenn man von jedem Inode jeweils nur den ersten gefundenen 
 Dateinamen wissen will, kann man oben statt 


   printf %s\\0 "$name" >> "$names"


   auch


   {
     test -e "$names" ||
     printf %s "$name" > "$names"
   }


 verwenden.  Dann erhält man von jedem Inode nur den ersten 
 Treffer. 

Back to de.comp.os.unix.shell | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

Gruppierung mit uniq für NUL-getrennte Daten? Tim Landscheidt <tim@tim-landscheidt.de> - 2025-10-12 14:15 +0000
  Re: Gruppierung mit uniq für NUL-getrennte Daten? ram@zedat.fu-berlin.de (Stefan Ram) - 2025-10-12 15:10 +0000
  Re: Gruppierung mit uniq für NUL-getrennte Daten? Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-10-12 22:57 +0200
    Re: Gruppierung mit uniq für NUL-getrennte Daten? Tim Landscheidt <tim@tim-landscheidt.de> - 2025-10-13 03:54 +0000
      Re: Gruppierung mit uniq für NUL-getrennte Daten? Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-10-13 20:53 +0200
        Re: Gruppierung mit uniq für NUL-getrennte Daten? Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-10-14 01:44 +0200
        Re: Gruppierung mit uniq für NUL-getrennte Daten? Christian Weisgerber <naddy@mips.inka.de> - 2025-10-14 14:00 +0000
      Re: Gruppierung mit uniq für NUL-getrennte Daten? Urs Janßen <urs@niko.tin.org> - 2025-10-14 06:18 +0000
        Re: Gruppierung mit uniq für NUL-getrennte Daten? ram@zedat.fu-berlin.de (Stefan Ram) - 2025-10-14 11:36 +0000
          Re: Gruppierung mit uniq für NUL-getrennte Daten? Urs Janßen <urs@niko.tin.org> - 2025-10-14 11:58 +0000
          Re: Gruppierung mit uniq für NUL-getrennte Daten? ram@zedat.fu-berlin.de (Stefan Ram) - 2025-10-14 15:46 +0000
    Re: Gruppierung mit uniq für NUL-getrennte Daten? Stefan Reuther <stefan.news@arcor.de> - 2025-10-13 16:58 +0200
      Re: Gruppierung mit uniq für NUL-getrennte Daten? Thomas Dorner <dcous251013.dorner@spamgourmet.com> - 2025-10-13 18:36 +0200

csiph-web