2008-11-27 8 views
9

Siempre que liste el contenido de un directorio con una función como readdir, los nombres de archivo devueltos también incluyen "." y "..". Tengo la sospecha de que estos son solo enlaces normales en el sistema de archivos y por lo tanto indistinguibles de los archivos reales, pero siempre tengo que filtrarlos porque no son objetos reales en el directorio que estoy enumerando. ¿Hay alguna buena razón para que funciones como readdir los incluya? ¿Algunos sistemas operativos o sistemas de archivos contienen más o diferentes nombres de archivos virtuales? ¿Hay una mejor manera de filtrarlos que no sea haciendo una comparación de cadenas con "." y ".."?¿Por qué las listas de directorios contienen el directorio actual (.) Y principal (...)?

Actualización: gracias a todos por responder. Supongo que siempre pensé que cosas como ./ y ../ eran meras convenciones que podrían manejarse buscando y reemplazando. Me parece un poco sorprendente, aunque probablemente más eficiente y transparente, hacer que formen parte del propio sistema de archivos.

Sin embargo, queda una pregunta: desde entonces. y ... son nombres arbitrarios para estos enlaces, ¿hay sistemas de archivos que utilicen otros?

Respuesta

11

. y .. son realmente enlaces duros en los sistemas de archivos. Son necesarios para que pueda especificar rutas relativas, basadas en alguna ruta de referencia (considere "../sibling/file.txt"). Como estos enlaces duros están realmente presentes en el sistema de archivos, tiene sentido que readdir le cuente sobre ellos. (En realidad, el término hard link solo significa un nombre que no se puede distinguir del directorio real al que se hace referencia: ambos apuntan al mismo inode en el sistema de archivos).

La mejor manera es simplemente strcmp e ignórelas, si no desea enumerarlas.

3

Una razón es que sin ellos no hay forma de llegar al directorio padre. O acceda al directorio actual.

Sin ellos, no podemos hacer cosas como: ''

./run_this 

De hecho, no podríamos añadir a $ PATH, lo que significa que no podríamos ejecutar archivos que no estuvieran en la ruta.

+0

En Windows,. parece ser parte de la RUTA implícitamente, lo que significa que simplemente puede escribir run_this. Al estar acostumbrado a esto, siempre he insistido en que el prefijo ./ es un poco molesto cuando uso Linux, aunque entiendo su valor para la seguridad. – Lemming

+0

No había pensado demasiado sobre las restricciones de seguridad hasta que se me explicó a principios de este año. El usuario desagradable podría tener un comando en su directorio llamado ls, que un administrador, al navegar a ese directorio, podría ejecutar, y ese comando podría permitirle al usuario acceso adicional. Malo. –

1

Estos son directorios normales, son "enlaces duros" al directorio y directorio actuales. Están presentes en todos los directorios (incluso en el nivel raíz, donde .. es exactamente igual que .).

Al utilizar ls, puede filtrar . y .. con ls -A (nótese la capital -A).

Cuando se aplica un comando a todos los archivos de puntos, pero no . o .., a menudo uso .??* la que sólo coincide punto-archivo con un nombre de tres caracteres o más.

touch .??* 

Nota este patrón también excluye cualquier otro archivo que comienza con punto y está a sólo dos caracteres de longitud (por ejemplo .x) pero esos archivos son infrecuentes.

Al usar listas de archivos programáticos como readdir() tengo que excluir . y .. manualmente. Dado que estos dos archivos se supone que deben ser los primeros en la lista devuelta por readdir() se puede hacer esto:

@files = readdir(DIR); 
for (1..2) { shift @files; } # get rid of . and .. 
# go on with your business 
+0

Esas dos líneas deberían ponerse en una función. – Svante

+0

¿Cómo sabes que no están * en * una función? :-) –

+0

Por extraño que parezca, en Windows, los directorios raíz (c: \, d: \, ...) no contienen ninguno de los dos enlaces. Al omitir el ... uno podría tener algún sentido, omitiendo. no. – Lemming

0

Según los informes, ya que se almacenan en el listado del directorio. Esa es la forma en que los unios siempre han funcionado.

0

Porque en los sistemas operativos tipo Unix, los comandos de listado de directorios incluyen esos, y los usa para subir y bajar en la jerarquía del sistema de archivos.

Algo así como grep { not /^.{1,2}\z/ } readdir HANDLE debería funcionar para usted.

+1

. , la cadena grep sería /^\.{1,2}$/, ya que el período necesita ser escapado. Probablemente escribiría esto como /^\.\.?$/. –

-4

no hay una buena razón para que un escaneo de directorio devuelva estos nombres de archivo.

+0

Existen todas las razones por las que un escaneo de directorio debe devolver estos nombres de archivo. ¿De qué otra manera escribes getcwd()? –

+0

de acuerdo. Sin . y ... no se puede manejar el directorio actual o uno principal. –

+0

Aunque no entiendo este argumento. Ya necesito saber el directorio actual para obtener su "." entrada en primer lugar ... – Lemming

3

Tengo la sospecha de que estos son simplemente enlaces normales en el sistema de archivos y, por tanto, indistinguibles de los archivos reales

Son. Si bien puede percibir el sistema de archivos como una jerarquía de "carpetas" que contienen "carpetas", en realidad es un árbol doblemente vinculado , con directorios que son nodos y archivos que son hojas. Por lo tanto, . y .. son necesarios enlaces para acceder a las hojas del nodo actual y para atravesar el árbol, y son lo mismo que todos los demás enlaces.

Cuando llama al readdir, obtiene todos los lugares a los que puede acceder directamente desde el nodo actual. Si no desea enumerar los lugares que percibe como "arriba", tiene que resolverlos usted mismo. Debería escribir una pequeña función para eso, quizás llamada readdir_down. No sé en qué orden readdir enumera los directorios, pero tal vez pueda descartar las dos primeras entradas.

) esta es una primera aproximación, también hay posibles "enlaces duros" que hacen que el árbol en realidad sea una red.

6

Originalmente eran enlaces duros, y el número de casos especiales en el código del sistema de archivos. y ... fueron mínimos. Sin embargo, eso no es cierto para todos los sistemas de archivos modernos.

Pero las convenciones se han establecido de modo que incluso los sistemas de archivos donde estas dos entradas de directorio realmente no existen todavía informan su existencia a través de API como readdir. Cambiar esto ahora rompería mucho código.

Cuestiones relacionadas