Comment puis-je utiliser le compteur de mots ( wc
) et la tuyauterie pour compter le nombre de fichiers ou de répertoires dans le /usr/bin
répertoire?
Comment puis-je utiliser le compteur de mots ( wc
) et la tuyauterie pour compter le nombre de fichiers ou de répertoires dans le /usr/bin
répertoire?
Réponses:
Une approche consisterait à utiliser ls
pour nous donner une liste des fichiers, mais nous voulons que cette liste soit garantie de ne montrer qu'un seul fichier ou répertoire par ligne. L' -1
interrupteur fera cela pour nous.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Créez les exemples de données ci-dessus dans un répertoire vide.
$ mkdir dir{1..3}
$ touch file{A..C}
Vérifie ça:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Maintenant, pour compter, vous pouvez utiliser wc -l
pour compter le nombre de lignes, qui correspondent à un fichier ou un répertoire dans la ls -1
sortie.
$ ls -1 | wc -l
6
(notez cependant qu'il n'inclut pas les fichiers cachés)
Pour compter les fichiers ou les répertoires, vous devez modifier légèrement votre tactique. Dans ce cas, j'utiliserais ls -l
car il montre ce qu'est un répertoire et ce qu'est un fichier.
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Ensuite, nous pouvons utiliser grep
pour filtrer les répertoires ou non-répertoires comme ceci:
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Maintenant, utilisez à wc -l
nouveau pour compter ce qui précède:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Cependant, vous pouvez éviter wc
complètement et utiliser grep
l' -c
option de:
$ ls -l | grep -c '^d'
(encore une fois, les fichiers cachés ne sont pas inclus. Notez que les répertoires et regular sont deux types de fichiers. Il y en a beaucoup plus comme des canaux nommés, des liens symboliques, des périphériques, des sockets ...).
Si vous devez trouver les fichiers et les répertoires de manière récursive sous, /usr/bin
vous voudrez probablement changer complètement de tactique et utiliser un autre outil appelé find
.
$ find /usr/bin | wc -l
4632
(même si au /usr/bin
- dessus de lui - même est inclus dans le décompte)
Les mêmes techniques que j'ai utilisées ci-dessus pourraient être utilisées ls
pour faire quelque chose de similaire, mais ce ls
n'est généralement pas un bon outil pour analyser la sortie. find
d'autre part, a été conçu pour cela et propose des commutateurs pour rechercher des fichiers ou des répertoires.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(notez que cette fois, find
inclut les fichiers cachés (sauf .
et ..
)).
Je n'ai jamais compris pourquoi un caractère de nouvelle ligne est un caractère légal à utiliser lors de la création de noms de fichiers ou de répertoires. Donc, les méthodes décrites ci-dessus les utilisent wc
et ls
ne les contesteraient pas, alors utilisez-les dans cet esprit.
Créez un répertoire et un nom de fichier avec des retours à la ligne.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
les montre correctement:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Mais wc
compte les répertoires et les fichiers qui contiennent des sauts de ligne comme 2 éléments, pas un.
$ ls -1 | wc -l
10
Une méthode pour contourner ce problème, si vous utilisez l'implémentation GNU de, find
est d'utiliser find
la capacité de pour imprimer quelque chose d'autre à la place de chaque fichier qu'il trouve, puis les compter à la place.
$ find . -printf . | wc -c
9
Ici , nous tout ce constat êtes la dans le répertoire courant (sauf ..
), et l' impression d' un point ( .
) pour chacun, puis compter les points en utilisant wc
la capacité de » count octets au lieu de lignes, wc -c
.
/usr/bin
soient tous bien formatés (et ne contiendront pas non plus d'espaces, donc techniquement vous pourriez même juste echo * | wc -w
), il convient de noter que tous ces éléments se briseront sur les noms de fichiers contenant des sauts de ligne.
ls -l
ou ls -1
va casser b / c on compte les lignes, pas les mots! Le find
peut casser, mais encore une fois, nous comptons des lignes et non des mots.
touch $'foo\nbar'
dans un répertoire vide suivi par l'une de vos commandes (disons ls -1 | wc -l
), vous rapporterez deux fichiers plutôt qu'un - car ce fichier est de deux lignes en ce qui wc
concerne. À moins de ls
remplacer les nouvelles lignes par un autre personnage (je ne pense pas, mais encore une fois je ne suis pas en mesure de tester pour le moment).
wc -c
un problème lors du comptage des périodes?
Si vous voulez obtenir une ventilation du nombre de chaque type de fichier récursivement sous un certain répertoire, avec GNU find
, vous pouvez faire:
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Sur /usr/bin
mon système, cela donne:
3727 regular files
710 symbolic links
Le /dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Pour les liens symboliques, si vous préférez les compter comme le type de fichier vers lequel ils pointent plutôt que symbolic links
, vous pouvez le changer en:
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Ce qui donne maintenant pour mon /usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(un lien symbolique rompu est un lien symbolique vers un fichier dont find
le type ne peut pas être déterminé soit parce que le fichier n'existe pas, soit dans un répertoire auquel vous n'avez pas accès ou qu'il y a une boucle dans la résolution du chemin du fichier Dans mon cas, ces 2 où les liens symboliques vers des fichiers qui ont maintenant disparu).
Aucun de ceux-là ne compte .
et ..
. Si vous vouliez les inclure (pourquoi le feriez-vous?), Il n'y a pas d'autre moyen find
que de supposer qu'ils sont là pour chaque répertoire et de les compter systématiquement:
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Ce qui donne alors sur mon /usr/bin
:
2 directories
3727 regular files
710 symbolic links
Si vous n'avez pas accès au GNU find
, vous pouvez réécrire le premier comme:
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
Maintenant, à proprement parler, nous ne comptons pas les fichiers mais les entrées de répertoire . Un répertoire comme /usr/bin
généralement possède plusieurs entrées qui pointent vers le même fichier. Par exemple, ici, j'ai:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
Ce sont 3 entrées de répertoire (aka noms de fichiers aka liens durs) dans le même fichier (celui avec inode 672252. Pour compter les fichiers au lieu des entrées de répertoire et avec GNU find
et GNU uniq
(ignorant .
et ..
fichiers qui de toute façon sont des liens durs vers d' autres répertoires):
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Sur mon /usr/bin
, cela donne:
3711 regular files
710 symbolic links
Vous n'avez pas dit si vous voulez que tout le fichier se trouve sous / usr / bin récursivement ou juste sous le premier niveau. Aussi, comment allez-vous obtenir les mots que vous comptez? La manière habituelle de le découvrir est d'exécuter find dans wc. Comme ceci: trouver / usr / bin | wc -l Find répertorie tout ce qui s'y trouve, répertoires et fichiers. Wc -l comptera toutes les lignes dans la sortie de recherche. Est-ce un devoir de classe? Ce n'est pas grave si c'est le cas, mais je me demandais pourquoi vous aviez besoin de ces informations pour que je puisse adapter la réponse plus soigneusement. Veuillez me faire savoir si vous en avez besoin de plus. Costa
En bash, sans outils externes.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
En bash, sans outils externes et récursivité.
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.
ni les ..
entrées. Vous voudrez peut-être lever l'ambiguïté du fichier par rapport au fichier normal.