¿Cuándo la cadena vacía indica el directorio actual?

¿Cuándo la cadena vacía indica el directorio actual?

En un script que uso findpara recopilar algunos archivos en el directorio actual, como en

$ find . -name "*.h"
./foo.h

Ahora me gustaría que solo salga foo.h, sin el ./prefijo. Pensé que la cadena vacía ""indicaba el directorio actual en los comandos del shell. Pero esto da:

$ find "" -name "*.h"
find: ftsopen: No such file or directory

Entonces me equivoqué. Ahora mi pregunta es ¿cuándo/cómo/dónde/... una "cadena vacía (?)" indica el directorio actual en los comandos que esperan un nombre de archivo o una ruta de acceso? ¿Existe una explicación clara y esclarecedora?

Una pregunta secundaria es si el problema de búsqueda anterior se puede resolver de manera simple, sin manipulación de cadenas como ${parameter#word}or cutor sed.

Respuesta1

Hace mucho tiempo (en 7ma edición, 32V, 4.2BSD, 4.3BSD), en el nivel de llamada al sistema, una ruta de acceso de longitud cero indicaba el directorio de trabajo actual (cuando se usaba para realizar búsquedas; no se permitía al intentar crear o eliminar un archivo o directorio). En Sistema III, fue un error utilizar una ruta de longitud cero en todas las circunstancias, y elestándar POSIXtiene esto que decir sobre la resolución de nombres de rutas:

Un nombre de ruta nulo no se resolverá exitosamente.

Respuesta2

Puedes usar:

find * -name "*.h"

Tenga en cuenta que los archivos en el directorio actual cuyo nombre comience con .se omitirán, y los archivos cuyo nombre comience con -serán interpretados como opciones findy causarán estragos, por lo que este no es un equivalente general a find . ….

La ausencia de una cadena que termine en " /" como parte de un nombre de archivoimplicael directorio actual, pero eso no significa que el directorio actual seadenotadopor una cadena vacía (que podría decirse que no es lo mismo que la ausencia de una cadena, aunque podría verse igual cuando se imprima).

Respuesta3

En general, la cadena vacía no indica el directorio actual, ni para comandos de shell ni en llamadas al sistema.Lo hizo en algunos sistemas más antiguos, pero no en sistemas compatibles con POSIX..

Ocasionalmente encontrará un programa que usa el directorio actual cuando pasa una cadena vacía y el programa espera un nombre de directorio. Esto a veces es deliberado y, a veces, un efecto secundario de anteponer la ruta absoluta del directorio actual cuando la cadena dada no comienza con una barra.

Lo mejor para ti sería dejar el ./. No hace ningún daño.

Si la lista de archivos es para

find . … | sed 's!^\./!!'

Tenga en cuenta que esto altera algunos nombres de archivos que contienen nuevas líneas. Por lo general, esto no es un problema para el consumo humano y la salida de findno es adecuada para el consumo de programas ya que es ambigua. Si está utilizando -print0, que es adecuado para el consumo de programas, probablemente no le importe el ./prefijo de todos modos.

Puedes utilizarlo find * …en lugar de find . …, pero ten en cuenta que find *tiene una serie de defectos que lo hacen inadecuado en general:

  • .se omite.
  • .Se omiten todos los archivos punto (archivos cuyo nombre comienza con o ..`).
  • Si hay un nombre de archivo en el directorio actual cuyo nombre comienza con -(o un archivo llamado !o (...), será interpretado como una opción o predicado por find.

El primer punto no importa si su filtro excluye el directorio actual. Para el segundo punto, puede usar los patrones ..?* .[!.]* *para que coincidan con todos los archivos en el directorio actual, pero deberá verificar si cada patrón coincide con al menos un archivo y omitirlo si no es así. Esto es posible pero muy engorroso. El último punto es un tapón. Por lo tanto, find *puede ser adecuado para un uso rápido en la línea de comandos, pero no lo use en un script.

Un enfoque alternativo es utilizar la función globbing recursiva del shell, por ejemplo

printf '%s\n' **/*.h

Esto debe activarse shopt -s globstaren bash y set -o globstaren ksh93, y no existe en un shell POSIX básico como dash. Los archivos Dot no se recorrerán de forma predeterminada; para incluirlos, primero haga que globbing no ignore los archivos dot en shopt -s dotglobbash o FIGNORE='@(.|..)'ksh93. Además, si no hay coincidencias, este comando imprime el patrón; ejecute shopt -s nullglobbash para imprimir una línea vacía y use el patrón ~(N)**/*.hen ksh.

En zsh, el globbing recursivo está activado de forma predeterminada. Utilice el calificador glob Dpara incluir archivos de puntos e Nimprimir una línea vacía si no hay coincidencias (de forma predeterminada, zsh genera un error si un patrón no coincide con ningún archivo). Puedes usar printfcomo arriba o

print -rl -- **/*.h(DN)

Respuesta4

Hay varios trucos que puedes usar para obtener el resultado de la búsqueda sin el encabezado ./:

  1. Utilice la opción de buscar -printfy dígale que solo imprima %f. Ver man find:

    %f Nombre del archivo con todos los directorios principales eliminados (solo el último elemento).

    Por ejemplo:

    find . -name "*.h" -printf "%f\n"
    
  2. Analizar la salida:

    find . -name "*.h" | sed 's#^./##'
    
  3. El truco de @Anthon

    find * -name "*.h"
    

En cuanto a su otra pregunta, la cadena vacía nunca indica el directorio actual. Es solo que varios programas toman el directorio actual como predeterminado, por lo que cuando los ejecuta sin argumentos, se ejecutan en el directorio actual.

información relacionada