¿Cómo puedo usar word counter ( wc) y piping para contar cuántos archivos o directorios hay en el /usr/bindirectorio?
¿Cómo puedo usar word counter ( wc) y piping para contar cuántos archivos o directorios hay en el /usr/bindirectorio?
Respuestas:
Un enfoque sería utilizar lspara darnos una lista de los archivos, pero queremos que se garantice que esta lista muestre solo 1 archivo o directorio por línea. El -1interruptor hará esto por nosotros.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Cree los datos de muestra anteriores en un directorio vacío.
$ mkdir dir{1..3}
$ touch file{A..C}
Revisalo:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Ahora para contar, puede usar wc -lpara contar el número de líneas, que corresponden a un archivo o directorio en la ls -1salida.
$ ls -1 | wc -l
6
(tenga en cuenta sin embargo que no incluye los archivos ocultos)
Para contar archivos o directorios, debe cambiar ligeramente su táctica. En este caso, lo usaría ls -lya que muestra qué es un directorio y qué es un archivo.
$ 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
Luego podemos usar greppara filtrar directorios o no directorios de esta manera:
# 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
Ahora solo use wc -lnuevamente para contar lo anterior:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Sin embargo, puede evitar por wccompleto y usar grepla -copción:
$ ls -l | grep -c '^d'
(de nuevo, los archivos ocultos no están incluidos. Tenga en cuenta que los directorios y los archivos regulares son dos tipos de archivos. Hay muchos más como canalizaciones con nombre, enlaces simbólicos, dispositivos, enchufes ...).
Si necesita encontrar los archivos y directorios de forma recursiva, /usr/binentonces es probable que desee cambiar las tácticas por completo y utilizar otra herramienta llamada find.
$ find /usr/bin | wc -l
4632
(aunque arriba /usr/binestá incluido en el recuento)
Las mismas técnicas que utilicé anteriormente podrían emplearse lspara hacer algo similar, pero lsgeneralmente no es una buena herramienta para analizar la salida. findPor otro lado, se creó para esto y ofrece conmutadores para buscar archivos o directorios.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(tenga en cuenta que esta vez, findincluye archivos ocultos (excepto .y ..)).
Nunca he descubierto por qué un carácter de nueva línea es un carácter legal para usar al crear nombres de archivo o nombres de directorio. Entonces, los métodos discutidos anteriormente usan wcy lsno competirían con estos, así que úselos con eso en mente.
Cree un directorio y nombre de archivo con nuevas líneas.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls los muestra correctamente:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Pero wccuenta los directorios y archivos que contienen nuevas líneas como 2 elementos, no uno.
$ ls -1 | wc -l
10
Un método para evitar esto, si utiliza la implementación de GNU findes utilizar findla capacidad de imprimir algo más en lugar de cada archivo que encuentra y luego contarlos.
$ find . -printf . | wc -c
9
Aquí estamos encontrando todo en el directorio actual (excepto ..), y la impresión de un punto ( .) para cada uno, y luego contar los puntos que utilizan wc's capacidad de contar bytes en lugar de líneas, wc -c.
/usr/binestarán bien formateados (y tampoco contendrán espacios, por lo que técnicamente podría simplemente echo * | wc -w), vale la pena señalar que todos estos se romperán en los nombres de archivo que contienen nuevas líneas.
ls -lo ls -1romperé b / c, estamos contando líneas, no palabras! El findpuede romper, pero de nuevo, estamos contando líneas no palabras.
touch $'foo\nbar'dentro de un directorio vacío seguido de uno de sus comandos (digamos ls -1 | wc -l) informará dos archivos en lugar de uno, porque ese archivo tiene dos líneas en lo que wcrespecta. A menos que lsreemplace las líneas nuevas con algún otro personaje (no creo que lo haga, pero nuevamente no estoy en condiciones de probarlo en este momento).
wc -cun problema al contar los períodos?
Si desea obtener un desglose del número de cada tipo de archivo de forma recursiva en algún directorio, con GNU find, puede hacer:
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 (&)/'
En /usr/binmi sistema, eso da:
3727 regular files
710 symbolic links
En /dev:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Para los enlaces simbólicos, si prefiere contarlos como el tipo de archivo al que apuntan en lugar de hacerlo symbolic links, puede cambiarlo a:
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 (&)/'
Lo que ahora da por mi /usr/bin:
1 directories
4434 regular files
2 broken symbolic links
(un enlace simbólico roto es un enlace simbólico a un archivo para el que findno se puede determinar el tipo, ya sea porque el archivo no existe, o está en un directorio al que no tiene acceso o hay un bucle en la resolución de la ruta del archivo En mi caso, esos 2 eran enlaces simbólicos a archivos que ahora se han ido).
Ninguno de esos cuenta .y ... Si quisieras incluirlos (¿por qué lo harías?), No hay otra forma findde asumir que están allí para cada directorio y contarlos sistemáticamente:
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 (&)/'
Que luego da en mi /usr/bin:
2 directories
3727 regular files
710 symbolic links
Si no tiene acceso a GNU find, puede reescribir el primero como:
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
Ahora, estrictamente hablando, no hemos estado contando archivos sino entradas de directorio . Un directorio como /usr/binsuele tener varias entradas que apuntan al mismo archivo. Por ejemplo, aquí tengo:
$ 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
Esas son 3 entradas de directorio (también conocidas como nombres de archivos también conocidos como enlaces duros) al mismo archivo (el que tiene el inodo 672252. Para contar archivos en lugar de entradas de directorio y con GNU findy GNU uniq(ignorando .y ..archivos que de todos modos son enlaces duros a otros directorios):
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 (&)/'
En mi /usr/bin, eso da:
3711 regular files
710 symbolic links
No ha dicho si quiere todo el archivo en / usr / bin de forma recursiva o solo en el primer nivel. Además, ¿cómo vas a obtener las palabras que estás contando? La forma habitual de averiguarlo es ejecutar find en wc. De esta manera: find / usr / bin | wc -l Find enumerará todo lo que hay allí, directorios y archivos. Wc -l contará todas las líneas en la salida de búsqueda. ¿Es esta una tarea de clase? Está bien si es así, pero me preguntaba por qué necesitabas esta información para poder adaptar la respuesta con más cuidado. Avísame si necesitas más. Costa
En bash, sin herramientas externas.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
En bash, sin herramientas externas y recursividad.
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 las ..entradas. Es posible que desee desagregar el archivo frente al archivo normal.