Rechercher des répertoires qui ne contiennent pas de sous-répertoires

10

J'écris le script est ksh. Besoin de trouver tous les noms de répertoire directement sous le répertoire actuel qui ne contiennent que des fichiers, pas des sous-répertoires.

Je sais que je pourrais utiliser ls -alRet analyser récursivement la sortie pour la première lettre du premier champ ( dpour un répertoire). Je pense que awkc'est la meilleure façon d'analyser et de trouver.

Par exemple, une simple ls -alsortie dans le répertoire courant:

   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
   

Il y a 2 répertoires dans cette sortie: Publicet Sites. Le répertoire Publicne contient pas de sous-répertoires, mais le Sitesfait. Il y a 3 sous-répertoires dans Sites. J'ai donc besoin d'écho uniquement les répertoires qui ne contiennent pas de répertoires. Dans mon cas, c'est seulement Sites.

Nat Kup
la source

Réponses:

1

Vous n'avez pas du tout besoin de l'utiliser awk. Utilisez les tests intégrés qui kshfournissent quelque chose comme ceci:

#!/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

Ce petit script regarde dans tous les répertoires du répertoire courant et vous indique s'ils ne contiennent que des fichiers, pas de sous-répertoires.

Bruce Ediger
la source
14

Si vous pouvez utiliser findet si vous travaillez sur un "système de fichiers Unix normal" (c'est-à-dire, comme défini dans find (1) sous la description de l'option -noleaf ), alors la commande suivante peut être utilisée:

find . -type d -links 2

Chaque répertoire a au moins 2 noms (liens durs): .et son nom. Le cas échéant, ses sous-répertoires ..pointeront vers le répertoire parent, donc un répertoire avec N sous-répertoires aura un nombre de liens durs égal à N + 2. Ainsi, en recherchant des répertoires avec un nombre de liens durs égal à 2, nous recherchons des répertoires avec N = 0 sous-répertoires.

Donc, si vous pouvez utiliser find, c'est sans doute la méthode la plus rapide et évidemment supérieure aux boucles dans le shell sur le contenu du répertoire stat()de chacun de ses membres.

intelfx
la source
Cela ne semble pas fonctionner si le répertoire contient des fichiers.
user394
1
Il ne s'agit pas d'entrées dans la liste du répertoire, il s'agit de liens durs faisant référence à l'inode du répertoire. Par exemple, si /some/directorya l'inode # 12345678, s'il n'a pas de sous-répertoires, il y aura exactement 2 liens durs vers cet inode: /some/directory/.et /some/directory. Cela fonctionne qu'il y ait ou non des fichiers dans le répertoire.
telcoM
Il convient de mentionner que BTRFS n'est pas un "système de fichiers Unix normal" à cet égard: les répertoires ont toujours un nombre de liens de 1, malheureusement. (Mais .et foo/..ont le même numéro d'inode.)
Peter Cordes
3

*/correspond aux sous-répertoires du répertoire courant. Cela inclut des liens symboliques vers des répertoires, que vous souhaitiez ou non.

Dans ksh93, l'ajout ~(N)au début du modèle le fait s'étendre à la liste vide s'il n'y a pas de correspondance. Sans cela, le modèle reste inchangé s'il n'y a pas de correspondance.

La fonction ksh93 suivante répertorie les sous-répertoires des répertoires actuels qui ne contiennent aucun sous-répertoire ni lien vers un répertoire.

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- arrête d'être méchant'
la source
0

si je ne vous comprends pas, vous voulez seulement trouver des fichiers dans le répertoire et non dans les sous-répertoires. Si telle est votre intention, voici la solution

find . -type f

si vous voulez trouver des fichiers autres que des fichiers normaux (comme les fichiers de périphériques de blocs, les fichiers de périphériques de caractères, etc.), consultez la page de manuel pour la findcommande et recherchez le mot-clé type sur cette page. Vous verrez différents types de fichiers, y compris des fichiers et des répertoires normaux, etc.

J'espère que c'est ce que vous recherchez

MelBurslan
la source
Non, ce n'est pas du tout la question. C'est assez clair une fois que vous avez installé / catalog / directory / g. Nat Kup recherche des répertoires qui ne contiennent pas de sous-répertoires.
Gilles 'SO- arrête d'être méchant'