Suchen Sie nach Verzeichnissen, die keine Unterverzeichnisse enthalten

10

Ich schreibe Skript ist ksh. Sie müssen alle Verzeichnisnamen direkt unter dem aktuellen Verzeichnis finden, die nur Dateien und keine Unterverzeichnisse enthalten.

Ich weiß, dass ich die ls -alRAusgabe für den ersten Buchstaben im ersten Feld ( dfür ein Verzeichnis) verwenden und rekursiv analysieren kann . Ich denke, das awkist der beste Weg, um zu analysieren und zu finden.

Zum Beispiel eine einfache ls -alAusgabe im aktuellen Verzeichnis:

   drwxr-xr-x  22 af      staff    748 18 Mar 22:21 .
   drwxr-xr-x   5 root    admin    170 17 Mar 18:03 ..
   -rw-------   1 af      staff      3 17 Mar 16:37 .CFUserTextEncoding
   drwxr-xr-x   5 af      staff    170 17 Mar 17:12 Public
   drwxr-xr-x   9 af      staff    306 18 Mar 17:40 Sites
   -rw-------   1 af      staff      3 17 Mar 16:37 textd
   

Diese Ausgabe enthält 2 Verzeichnisse: Publicund Sites. Das Verzeichnis Publicenthält keine Unterverzeichnisse, Sitestut es aber . Es gibt 3 Unterverzeichnisse in Sites. Ich muss also nur die Verzeichnisse wiedergeben, die keine Verzeichnisse enthalten. In meinem Fall ist dies nur Sites.

Nat Kup
quelle

Antworten:

1

Sie müssen überhaupt nicht verwenden awk. Verwenden Sie die integrierten Tests, kshdie Folgendes bieten:

#!/bin/ksh

for NAME in *
do
    FOUND=no
    if [[ -d $NAME && $NAME != '.' && $NAME != '..' ]]
    then
        for SUBNAME in $NAME/*
        do
            if [[ -d $SUBNAME ]]
            then
                FOUND=yes
                break
            fi
        done
        if [[ $FOUND == no ]]
        then
            echo Found only files in $NAME
        fi
    fi
done

Dieses kleine Skript durchsucht alle Verzeichnisse im aktuellen Verzeichnis und teilt Ihnen mit, ob sie nur Dateien und keine Unterverzeichnisse enthalten.

Bruce Ediger
quelle
14

Wenn Sie in der Lage findsind, ein "normales Unix-Dateisystem" zu verwenden ( dh wie in find (1) unter Beschreibung der Option -noleaf definiert ), kann der folgende Befehl verwendet werden:

find . -type d -links 2

Jedes Verzeichnis hat mindestens 2 Namen (Hardlinks): .und seinen Namen. Die Unterverzeichnisse, falls vorhanden, ..verweisen auf das übergeordnete Verzeichnis, sodass ein Verzeichnis mit N Unterverzeichnissen eine feste Verbindungsanzahl von N + 2 aufweist. Wenn wir also nach Verzeichnissen mit einer festen Verbindungsanzahl von 2 suchen, suchen wir nach Verzeichnissen mit N = 0 Unterverzeichnissen.

Wenn Sie also verwenden können find, ist dies wohl die schnellste Methode und offensichtlich besser als In-Shell-Schleifen über den Verzeichnisinhalt stat()jedes einzelnen Mitglieds.

intelfx
quelle
Dies scheint nicht zu funktionieren, wenn das Verzeichnis Dateien enthält.
user394
1
Es geht nicht um Einträge in der Verzeichnisliste, sondern um feste Links, die auf den Inode des Verzeichnisses verweisen. Wenn beispielsweise /some/directoryder Inode # 12345678 vorhanden ist und keine Unterverzeichnisse vorhanden sind, gibt es genau zwei feste Links zu diesem Inode: /some/directory/.und /some/directory. Es funktioniert unabhängig davon, ob sich Dateien im Verzeichnis befinden oder nicht.
TelcoM
Erwähnenswert ist, dass BTRFS in dieser Hinsicht kein "normales Unix-Dateisystem" ist: Verzeichnisse haben leider immer eine Linkanzahl von 1. (Aber .und foo/..haben die gleiche Inode-Nummer.)
Peter Cordes
3

*/stimmt mit den Unterverzeichnissen des aktuellen Verzeichnisses überein. Dies schließt symbolische Links zu Verzeichnissen ein, die Sie möglicherweise wünschen oder nicht.

~(N)Wenn Sie in ksh93 am Anfang des Musters hinzufügen , wird es zur leeren Liste erweitert, wenn keine Übereinstimmung vorliegt. Ohne dies bleibt das Muster unverändert, wenn keine Übereinstimmung vorliegt.

Die folgende Funktion ksh93 listet die Unterverzeichnisse der aktuellen Verzeichnisse auf, die kein Unterverzeichnis oder keinen Link zu einem Verzeichnis enthalten.

list_leaf_directories () {
  local FIGNORE='.?(.)'        # don't ignore dot files
  local d
  for d in */; do
    [[ -L $d ]] || continue;   # skip symbolic links
    set -- ~(N)"$d"/*/
    if ((!$#)); then echo "$d"; fi
  done
done
Gilles 'SO - hör auf böse zu sein'
quelle
0

Wenn ich Sie nicht missverstehe, möchten Sie nur Dateien im Verzeichnis finden, nicht in den Unterverzeichnissen. Wenn dies Ihre Absicht ist, ist hier die Lösung

find . -type f

Wenn Sie andere als normale Dateien suchen möchten (z. B. Blockgerätedateien, Zeichengerätedateien usw.), lesen Sie in der Manpage den findBefehl und suchen Sie auf dieser Seite nach dem Schlüsselwort type . Sie sehen verschiedene Dateitypen, einschließlich regulärer Dateien und Verzeichnisse usw.

Hoffe das ist was du suchst

MelBurslan
quelle
Nein, das ist überhaupt nicht die Frage. Es ist ziemlich klar, wenn Sie s / catalog / directory / g. Nat Kup sucht nach Verzeichnissen, die keine Unterverzeichnisse enthalten.
Gilles 'SO - hör auf böse zu sein'