¿Cómo puedo usar word counter ( wc
) y piping para contar cuántos archivos o directorios hay en el /usr/bin
directorio?
¿Cómo puedo usar word counter ( wc
) y piping para contar cuántos archivos o directorios hay en el /usr/bin
directorio?
Respuestas:
Un enfoque sería utilizar ls
para darnos una lista de los archivos, pero queremos que se garantice que esta lista muestre solo 1 archivo o directorio por línea. El -1
interruptor 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 -l
para contar el número de líneas, que corresponden a un archivo o directorio en la ls -1
salida.
$ 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 -l
ya 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 grep
para 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 -l
nuevamente 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 wc
completo y usar grep
la -c
opció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/bin
entonces 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/bin
está incluido en el recuento)
Las mismas técnicas que utilicé anteriormente podrían emplearse ls
para hacer algo similar, pero ls
generalmente no es una buena herramienta para analizar la salida. find
Por 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, find
incluye 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 wc
y ls
no 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 wc
cuenta 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 find
es utilizar find
la 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/bin
estará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 -l
o ls -1
romperé b / c, estamos contando líneas, no palabras! El find
puede 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 wc
respecta. A menos que ls
reemplace 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 -c
un 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/bin
mi 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 find
no 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 find
de 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/bin
suele 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 find
y 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.