Que sont les répertoires ./ et ../?

20

Question simple, mais je ne sais pas où chercher et google ne répond pas aux règles et aux barres obliques.

J'essaie simplement de compter le nombre de fichiers et de répertoires dans le répertoire actuel (sans inclure les sous-dossiers / fichiers) et j'essayais de les différencier ls -1 | wc -let ls | wc -lcar ils semblent identiques. Un site que je consultais disait "Gardez à l'esprit que cela compte également les répertoires ./ et ../." en ce qui concerne celui avec ls -1, et je ne sais pas si cela signifie qu'il inclut les répertoires avant ou quelque chose (ce que je ne veux pas), mais il ne semble pas que cela ait été fait à partir des tests.

Quelqu'un pourrait-il confirmer lequel serait le plus approprié pour compter le nombre de fichiers et de répertoires dans le répertoire en cours uniquement (pas de sous-répertoire) et ce qu'ils entendent par les répertoires ./ et ../?

Adam
la source
Le "Gardez à l'esprit que cela compte également les répertoires ./ et ../" est faux (sauf s'il s'agit d'une faute de frappe pour "." Et "..".
vonbrand

Réponses:

15

Chaque répertoire sur un système Unix (et probablement tous les autres systèmes aussi) contient au moins deux entrées de répertoire. Ce sont .(répertoire courant) et ..(répertoire parent). Dans le cas du répertoire racine, ceux-ci pointent au même endroit, mais avec tout autre répertoire, ils sont différents. Vous pouvez le constater par vous-même en utilisant les commandes stat, pwdet cd(sous Linux):

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$

Notez cela binet sbinchacun a deux liens. L'un est l'entrée de répertoire dans le répertoire racine et l'autre est l' .entrée dans ce répertoire.

L'utilisation lsavec un tube to wc -lest une astuce simple pour compter le nombre de lignes dans la sortie de ls. L'hypothèse est que chaque fichier ou répertoire occupera exactement une ligne dans la sortie. GNU ls le fera automatiquement lorsque la sortie est non terminale; d'autres peuvent avoir besoin de l' -1option pour activer explicitement le comportement. wc -lcompte et affiche simplement le nombre de lignes ( -l) dans son entrée.

Le problème avec cette approche est que sous Linux et sur les systèmes de fichiers traditionnellement utilisés sous Linux, les noms de fichiers et de répertoires (ils sont vraiment les mêmes à cet égard) sont autorisés à contenir des caractères de nouvelle ligne . En présence de ceux-ci, l'une ou l'autre méthode s'effondre - ces entrées seront comptées comme deux entrées ou plus alors qu'en réalité elles ne font qu'un.

Tant que vous utilisez GNU ls, n'avez aucune entrée de répertoire avec des noms contenant des caractères de nouvelle ligne, et n'avez pas d'alias impairs pour ls(par exemple, ls -a), les deux afficheront le nombre de fichiers et de répertoires dans le répertoire actuel (ou spécifié). Pour la plupart des gens, c'est suffisant, mais ce n'est pas valable dans le cas général .

Si vous devez gérer correctement les caractères inhabituels (principalement les sauts de ligne) dans les noms des entrées de répertoire, je suggère d'utiliser l' -boption ls pour les échapper. ls -1bAimprimera chaque nom d'entrée de répertoire sur sa propre ligne, échappera les caractères inhabituels (de sorte que chaque entrée de répertoire sera considérée comme une seule), y compris les fichiers de points et les répertoires. Tack on wc -lpour une ligne de commande complète ls -1bA | wc -lqui rapportera le nombre de fichiers et de répertoires dans le répertoire actuel (mais ignorez .et ..; c'est la différence entre -aet -A), mais ne descendez dans aucun sous-répertoire. Si vous ne voulez pas que les fichiers dot soient comptés dans le total, omettez simplement le -Aparamètre à ls.

un CVn
la source
Les deux -aet -Aincluent également les fichiers cachés que j'ai réalisé que je veux éviter, donc tout au plus je le ferais ls -b | wc -l, mais cela me donne la bonne réponse. La ligne copiée et collée concernant cette commande est-elle incorrecte? Si c'était correct, ne devrais-je pas obtenir une sortie de 8 alors qu'il y a 6 fichiers ou dossiers dans un répertoire?
Adam
@Adam oui, cela fera probablement l'affaire ("ls -b | wc -l"); vous pouvez également utiliser le "-1" (tiret + numéro un) qui force une liste dans une seule colonne au lieu de tout sur une seule ligne, mais cela se produit quand même lorsque vous redirigez vers une autre commande. Donc (à mon humble avis) je le laisserais comme "ls -1b | wc -l"; et pour "tester", exécutez "ls -1b" et comptez le nombre de lignes, puis exécutez "ls -1b | wc -l" et vérifiez les résultats. (Voilà comment déboguer / tester des tuyaux.)
Michael
@Sardathrion, cette FAQ est assez trompeuse. Les conventions du système de fichiers Unix ne sont pas "étranges"; là où ils sont communs, c'est l' autre système qui les prend. Mais d'accord. Ensuite, il dit que la "commande de fichier utilise des nombres magiques pour identifier ...", ce qui est faux: elle utilise également beaucoup d'heuristiques. Pas très fiable dans mon livre.
vonbrand
@vonbrand: assez juste, lien supprimé. Je l'ai juste effleuré et ça semblait bien. Je sais que j'en ai trouvé un qui était bon, mais je ne me souviens plus où c'était.
Sardathrion
1
Tu te trompes: . et .. sont des artefacts historiques d'UNIX dans les années 1970 et résultent d'une époque où il n'y avait pas mkdir()encore d'appel système. Tous les systèmes de fichiers ne les ont pas et ils ne sont même pas nécessaires ni requis par POSIX.
schily
6

Pour répondre à la question sur le sujet:

Lorsqu'un répertoire B est créé sous Unix, il est ajouté en tant que nouvelle entrée à un autre répertoire A (son répertoire parent) et en B, deux entrées sont ajoutées: une appelée en .tant que lien dur vers elle-même et une appelée en ..tant que disque dur. lien vers A.

Ce sont les seuls liens durs vers les répertoires autorisés (bien que certaines anciennes versions de certains Unices autorisent également les liens arbitraires).

c'est pourquoi avec la plupart des systèmes de fichiers ( btrfsétant une exception notable), le nombre d' linksun répertoire est une indication du nombre de sous-répertoires qu'il possède (en tenant compte de leurs ..entrées).

Lorsque vous renommez / déplacez un répertoire, s'il s'agit du même répertoire (sous un nom différent), seule l'entrée de nom dans Aest modifiée. B .et ..n'est pas affecté. Mais si vous le déplacez faire un autre répertoire, puis ..en Bva changer. Cela explique pourquoi vous pouvez renommer un répertoire sur lequel vous n'avez pas accès en écriture (en supposant que vous avez un accès en écriture au répertoire parent) tant que vous ne le déplacez pas vers un autre répertoire (sinon la nécessité de modifier l' ..entrée empêche vous de le déplacer).

Attention cependant: /a/b/../cpeut ne pas être le même que /a/cparce qu'il /a/bpeut s'agir d'un lien symbolique vers un autre répertoire.

Une exception à cela est lorsque ce chemin est donné à la cdcommande pour certains shells. Ces cds traitent .. logiquement en ignorant les ..entrées dans les répertoires. Une raison pour laquelle vous voyez souvent cd -Pdans des scripts correctement écrits, la désactivation de cette fonctionnalité qui pourrait autrement causer de la confusion et des incohérences.

Pour compter le nombre d'entrées dans le répertoire courant hors .et ..avec bash, vous pouvez:

shopt -s nullglob dotglob
set -- *
echo "$#"

Avec zsh:

f=(*(ND))
echo $#f

Portablement:

find . ! -name . -prune -print | grep -c /
Stéphane Chazelas
la source
Je suis un peu confus; les trois que vous avez énumérés en ajoutent un au décompte réel. Par exemple, si j'ai 6 fichiers ou dossiers dans un répertoire, ils en produisent 7, pas 6. Pour moi, il semble que ce ls | wc -lsoit le seul à exclure .et..
Adam
1
@Adam, lsne répertorie pas les fichiers cachés. Vous devez ls -Aobtenir les mêmes que ceux-ci. SI vous ne voulez pas compter les fichiers cachés, décochez dotglob(pour bash) ou D(pour zsh) ou ajoutez un ! -name '.*'avant -printpour find.
Stéphane Chazelas
Oui, je viens de le remarquer après avoir répertorié les fichiers. Savez-vous alors pourquoi ls | wc -lme donne toujours la bonne réponse et exclut les fichiers cachés, .& ..?
Adam
1
Adam, dans votre répertoire, vous avez ., ..et un autre fichier dont le nom commence par .qui n'est pas répertorié par ls mais serait par ls -A. Donc, ls | wc -lne vous donne pas la bonne réponse car il ne compte pas ce fichier caché.
Stéphane Chazelas
1
Oui, .et ..sont des fichiers cachés car ils commencent par un .. Il y a même une légende qui explique que les fichiers dot sont cachés par accident car une implémentation précoce de lsétait censée exclure uniquement .et .., mais il y avait un bogue qui l'a obligé à exclure tout fichier commençant par .. ls | wc -lne fonctionne pas si les noms de fichiers contiennent des caractères de nouvelle ligne.
Stéphane Chazelas
1

Je ne suis pas un grand expert Linux, mais je connais Linux (anciennement administrateur il y a 16 ans, sur Slackware :) bon vieux temps

les répertoires ./ et ../ c'est simple:. est le répertoire courant, .. est le répertoire précédent (dans l'arborescence de pwd -local directory command-

Si cela les compte, je pense qu'ils ajoutent 2 au total de la liste, ne vont pas vraiment récursivement et comptent le répertoire en dessous de celui en cours, et comptent également à nouveau le répertoire actuel (.) :))

Donc, fondamentalement, je pense qu'il ajoute la valeur 2 à déjà compter (fichiers) dans le répertoire actuel.

Quiconque me corrige si je me trompe.

Je poste juste pour aider et vu que personne n'a répondu à cette question ici, ils pourraient être occupés. Mais expérimentez et voyez si vous avez 10 fichiers et obtenez le nombre de 12, alors c'est tout.

Adrian Tanase
la source
Oui, Adrian a raison:. est le répertoire courant et .. est le répertoire immédiatement supérieur dans la hiérarchie.
schaiba
.. ne fait pas toujours référence au répertoire précédent dans l'arborescence: dans "/" .. fait également référence au répertoire courant.
Bonsi Scott
parce que vous pourriez être dans / root du système de fichiers?
Adrian Tanase
Si cela ajoute deux au nombre de fichiers dans un répertoire, pourquoi ai-je la bonne réponse lors du test dans le terminal sur osx? par exemple, un répertoire avec 6 fichiers ou dossiers produira 6, pas 8 quand je le faisls | wc -1
Adam
J'ai réalisé que c'est parce qu'ils incluent des fichiers cachés (à savoir .ds_store), mais je ne vois toujours pas comment ls | wc -linclut .et ..quand j'obtiens la bonne réponse, par opposition à la bonne réponse + 2.
Adam