¿Qué son los directorios ./ y ../?

20

Pregunta simple, pero no estoy seguro de dónde buscar y google no responde a los puntos y las barras.

Sólo estoy tratando de contar el # de archivos y directorios en el directorio actual (sin incluir subcarpetas / archivos) y estaba tratando de diferenciar ls -1 | wc -ly ls | wc -lya que parecen idénticos. Un sitio que estaba viendo decía "Tenga en cuenta que esto también cuenta los directorios ./ y ../". con respecto al que tiene ls -1, y no estoy seguro de si eso significa que incluye los directorios antes o algo (que no quiero), pero parece que no lo hizo durante las pruebas.

¿Podría alguien confirmar cuál de esos sería el más adecuado para contar # de archivos y directorios en el directorio actual solamente (no sub) y qué quieren decir con ./ y ../ directorios?

Adán
fuente
El "Tenga en cuenta que esto también está contando los directorios ./ y ../" está mal (a menos que sea un error tipográfico para "." Y "..".
vonbrand

Respuestas:

15

Cada directorio en un sistema Unix (y probablemente también en cualquier otro sistema) contiene al menos dos entradas de directorio. Estos son .(directorio actual) y ..(directorio padre). En el caso del directorio raíz, estos apuntan al mismo lugar, pero con cualquier otro directorio, son diferentes. Esto se puede ver por sí mismo utilizando los stat, pwdy cdcomandos (en 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
/
$

Observe eso biny sbincada uno tiene dos enlaces. Una es la entrada del directorio en el directorio raíz, y la otra es la .entrada dentro de ese directorio.

Usar lscon un pipe to wc -les un truco simple para contar el número de líneas en la salida de ls. La suposición es que cada archivo o directorio ocupará exactamente una línea en la salida. GNU ls, cuando la salida es no terminal, lo hará automáticamente; otros pueden necesitar la -1opción de activar el comportamiento explícitamente. wc -lsimplemente cuenta y genera el número de líneas ( -l) en su entrada.

El problema con ese enfoque es que en Linux y en los sistemas de archivos utilizados tradicionalmente en Linux, los nombres de archivos y directorios (en realidad son uno y el mismo en este sentido) pueden contener caracteres de nueva línea . En presencia de esos, cualquiera de los métodos se desmorona: esas entradas se contarán como dos o más entradas cuando en realidad son una.

Mientras esté utilizando GNU ls, no tenga entradas de directorio con nombres que contengan caracteres de nueva línea y no tenga alias impares para ls(por ejemplo ls -a), ambos generarán el recuento de archivos y directorios en el directorio actual (o especificado). Para la mayoría de las personas, esto es lo suficientemente bueno, pero no es válido en el caso general .

Si necesita manejar caracteres inusuales (principalmente nuevas líneas) en los nombres de entrada de directorio correctamente, sugiero usar la -bopción ls para escapar de ellos. ls -1bAimprimirá cada nombre de entrada de directorio en su propia línea, escapará de caracteres inusuales (para que cada entrada de directorio se vea como una), incluidos los archivos de puntos y los directorios. Marque wc -lpara obtener una línea de comando completa de la ls -1bA | wc -lcual informará el número de archivos y directorios en el directorio actual (pero ignore .y ..; esa es la diferencia entre -ay -A), pero no descenderá a ningún subdirectorio. Si no desea que ningún archivo de puntos se cuente para el total, simplemente omita el -Aparámetro ls.

un CVn
fuente
Ambos -ae -Aincluyen también archivos ocultos que me di cuenta de que quiero evitar, así que a lo sumo lo haría ls -b | wc -l, pero esto me da la respuesta correcta. ¿Es incorrecta la línea que copio y pego con respecto a este comando? Si era correcto, ¿no debería obtener una salida de 8 cuando hay 6 archivos o carpetas en un directorio?
Adam
@ Adam, sí, eso probablemente hará el truco ("ls -b | wc -l"); También puede usar el "-1" (guión + número uno) que fuerza una lista en una sola columna en lugar de todo en una sola línea, pero eso sucede de todos modos cuando se canaliza a otro comando. Entonces (en mi humilde opinión) lo dejaría como "ls -1b | wc -l"; y para "probar", ejecute "ls -1b" y cuente el número de líneas, luego ejecute "ls -1b | wc -l" y verifique los resultados. (Así es como depurar / probar tuberías.)
michael
@Sardathrion, esa pregunta frecuente es bastante engañosa. Las convenciones del sistema de archivos Unix no son "extrañas"; donde son comunes es el otro sistema que los recoge. Pero está bien. Luego dice que el "comando de archivo usa números mágicos para identificar ...", lo cual es incorrecto: también usa muchas heurísticas. No es muy confiable en mi libro.
vonbrand
@vonbrand: bastante justo, enlace eliminado. Simplemente lo hojeé y me pareció bien. Sé que encontré uno que era bueno, pero ahora no puedo recordar dónde estaba.
Sardathrion - Restablece a Mónica el
1
Estás equivocado: . y ... son artefactos históricos de UNIX en la década de 1970 y son el resultado de un momento en que todavía no había una mkdir()llamada al sistema. No todos los sistemas de archivos los tienen y ni siquiera son necesarios ni requeridos por POSIX.
schily
6

Para responder la pregunta en el tema:

Cuando se crea un directorio B en Unix, se agrega como una nueva entrada a otro directorio A (su directorio padre), y en B, se agregan dos entradas: una llamada .como un enlace rígido a sí mismo y otra llamada ..como un disco duro enlace a A.

Esos son los únicos enlaces duros a directorios permitidos (aunque algunas versiones anteriores de algunos Unices también permitían enlaces arbitrarios).

Es por eso que con la mayoría de los sistemas de archivos ( btrfssiendo una notable excepción), el número delinks de un directorio es una indicación de cuántos subdirectorios tiene (contabilizando sus ..entradas).

Cuando renombra / mueve un directorio, si está en el mismo directorio (con un nombre diferente), solo Ase cambia la entrada del nombre . B .y ..no se ve afectado. Pero si se mueve hacer un directorio diferente, entonces ..en Bcambiará. Eso explica por qué puede cambiar el nombre de un directorio en el que no tiene acceso de escritura (suponiendo que tenga acceso de escritura al directorio principal) solo mientras no lo mueva a otro directorio (de lo contrario, la necesidad de cambiar el.. entrada impide usted de moverlo).

Sin embargo, /a/b/../ctenga cuidado: puede que no sea lo mismo que /a/cporque /a/bpodría ser un enlace simbólico a otro directorio.

Una excepción a eso es cuando esa ruta se le da al cdcomando a algunos shells. Esos cds tratan .. lógicamente ignorando las ..entradas en los directorios. Una razón por la que a menudo se ve cd -Pen scripts escritos correctamente, para deshabilitar esa característica que de lo contrario podría causar confusión e inconsistencias.

Para contar el número de entradas en el directorio actual excluyendo .y ..con bash, puede hacer:

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

Con zsh:

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

Portablemente:

find . ! -name . -prune -print | grep -c /
Stéphane Chazelas
fuente
Estoy un poco confundido; los tres que enumeró agregan uno al recuento real. por ejemplo, si tengo 6 archivos o carpetas en un directorio, generan 7, no 6. Para mí, parece que ls | wc -les el único que excluye .y..
Adam
1
@ Adam, lsno enumera los archivos ocultos. Necesitas ls -Aobtener lo mismo que esos. SI no desea contar los archivos ocultos, elimine dotglob(para bash) o D(para zsh) o agregue un ! -name '.*'antes -printpara find.
Stéphane Chazelas
Sí, acabo de notar esto después de enumerar los archivos. ¿Sabes entonces por qué ls | wc -ltodavía me da la respuesta correcta y excluye los archivos ocultos, .y ..?
Adam
1
Adam, en tu directorio, tienes ., ..y otro archivo cuyo nombre comienza con el .que no está enlistado por ls pero sí por ls -A. Por ls | wc -llo tanto, no le da la respuesta correcta porque no cuenta ese archivo oculto.
Stéphane Chazelas
1
Sí, .y ..son archivos ocultos ya que comienzan con a .. Incluso hay una leyenda que explica que los archivos de puntos están ocultos por accidente, ya que una implementación temprana lssolo debía excluir .y .., pero hubo un error que hizo que excluyera cualquier archivo que comenzara con .. ls | wc -lno funciona si los nombres de archivo contienen caracteres de nueva línea.
Stéphane Chazelas
1

No soy un gran experto en Linux, pero sé que Linux (solía ser administrador hace 16 años, en Slackware :) buenos viejos tiempos

los directorios ./ y ../ es simple:. es el directorio actual, .. es el directorio anterior (en el árbol de pwd -comando de directorio local-

Si los cuenta, creo que agregan 2 al total de la lista, en realidad no van recursivamente y cuentan el directorio debajo del actual, y también cuentan nuevamente el directorio actual (.) :))

Básicamente, creo que agrega el valor 2 para contar (archivos) en el directorio actual.

Alguien corríjame si me equivoco.

Solo estoy publicando para ayudar y vi que nadie respondió a esta pregunta aquí, podrían estar ocupados. Pero solo experimente y vea si tiene 10 archivos y cuenta hasta 12, entonces eso es todo.

Adrian Tanase
fuente
Sí, Adrian tiene razón:. es el directorio actual y ... es el directorio inmediatamente superior en la jerarquía.
schaiba
.. no siempre se refiere al directorio anterior en el árbol: en "/" .. también se refiere al directorio actual.
Bonsi Scott
porque podrías estar en / root del sistema de archivos?
Adrian Tanase
Si agrega dos al número de archivos en un directorio, ¿por qué obtengo la respuesta correcta al probarlo en la terminal en osx? por ejemplo, un directorio con 6 archivos o carpetas generará 6, no 8 cuando lo hagals | wc -1
Adam
Me di cuenta de que es porque incluyen archivos ocultos (es decir .ds_store), pero todavía no veo cómo ls | wc -lincluye .y ..cuándo obtengo la respuesta correcta, en lugar de la respuesta correcta + 2.
Adam