Cómo extraer el nombre de archivo de la ruta

Debe haber algo elegante en Linux API / POSIX para extraer el nombre del archivo base de la ruta completa. Gracias.

Ver char *basename(char *path) .

O ejecute el comando ” man 3 basename ” en su sistema UNIX / POSIX de destino.

Use basename (que tiene una semántica de caso de esquina impar) o hágalo usted mismo llamando a strrchr(pathname, '/') y tratando la cadena completa como un nombre base si no contiene un carácter '/' .

Aquí hay un ejemplo de una línea (dado char * whoami ) que ilustra el algoritmo básico:

 (whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]); 

se necesita una verificación adicional si NULL es una posibilidad. También tenga en cuenta que esto solo apunta a la cadena original, un ” strdup() ” puede ser apropiado.

Podría usar strstr en caso de que también esté interesado en los nombres de directorio:

 char *path ="ab/cde/fg.out"; char *ssc; int l = 0; ssc = strstr(path, "/"); do{ l = strlen(ssc) + 1; path = &path[strlen(path)-l+2]; ssc = strstr(path, "/"); }while(ssc); printf("%s\n", path); 

Por supuesto, si esta es una pregunta de solo Gnu / Linux, entonces podría usar las funciones de la biblioteca.

https://linux.die.net/man/3/basename

Y aunque algunos pueden rechazar estas funciones compatibles con POSIX Gnu Library no usan const. Como las funciones de utilidad de la biblioteca rara vez lo hacen. Si eso es importante para usted, supongo que tendrá que atenerse a su propia funcionalidad o tal vez lo siguiente sea más de su agrado.

 #include  #include  int main(int argc, char *argv[]) { char *fn; char *input; if (argc > 1) input = argv[1]; else input = argv[0]; /* handle trailing '/' eg input == "/home/me/myprogram/" */ if (input[(strlen(input) - 1)] == '/') input[(strlen(input) - 1)] = '\0'; (fn = strrchr(input, '/')) ? ++fn : (fn = input); printf("%s\n", fn); return 0; } 

La función basename() devuelve el último componente de una ruta, que podría ser un nombre de carpeta y no un nombre de archivo. Hay dos versiones de la función basename() : la versión GNU y la versión POSIX.

La versión de GNU se puede encontrar en string.h después de incluir #define _GNU_SOURCE :

     # define _GNU_SOURCE

     #include 

La versión GNU usa const y no modifica el argumento.

  char * nombre base (const char * ruta) 

Esta función está anulada por la versión XPG (POSIX) si se incluye libgen.h .

  char * nombre base (char * ruta) 

Esta función puede modificar el argumento eliminando los bytes ‘/’ finales. El resultado puede ser diferente de la versión GNU en este caso:

  nombre base ("foo / bar /") 

devolverá la cadena “barra” si usa la versión XPG y una cadena vacía si usa la versión GNU.

Referencias:

    nombre base (3) – Linux Man Pages
    Función: char * basename (const char * filename) , Encontrar tokens en una cadena.

 template chatType* getFileNameFromPath( chatType* path ) { if( path == NULL ) return NULL; chatType * pFileName = path; for( chatType * pCur = path; *pCur != '\0'; pCur++) { if( *pCur == '/' || *pCur == '\\' ) pFileName = pCur+1; } return pFileName; } 

call: wchar_t * fileName = getFileNameFromPath (filePath);

No quiero ser exagerado aquí en lo que otras personas publican, pero …

  1. Llamar a algunas funciones “caseras” sugeridas (como: getFileNameFromPath("") ) bloqueará el progtwig.
  2. Recomendaría un poco de precaución al nombrar funciones que de forma inherente afirmen que el resultado será un archivo. getFilenameFromPath("/usr/local") devolverá "local" (sin las comillas), aunque en un sistema de archivos Unix es generalmente el caso de que sea una carpeta.

Puedes escapar de las barras oblicuas a la barra invertida y usar este código:

 #include  #include  int main(void) { char path[] = "C:\\etc\\passwd.c"; //string with escaped slashes char temp[256]; //result here char *ch; //define this ch = strtok(path, "\\"); //first split while (ch != NULL) { strcpy(temp, ch);//copy result printf("%s\n", ch); ch = strtok(NULL, "\\");//next split } printf("last filename: %s", temp);//result filename return 0; } 

Mi ejemplo

 const char* getFileNameFromPath(const char* path) { for(size_t i = strlen(path) - 1; i >= 0; i--) { if (path[i] == '/') { return &path[i+1]; } } return path; } 

@Nikolay Khilyuk ofrece la mejor solución excepto.

1) Vuelva a usar char *, no hay absolutamente ninguna buena razón para usar const.

2) Este código no es portátil y es probable que falle en ninguno de los sistemas POSIX donde el / no es el delimitador del sistema de archivos dependiendo de la implementación del comstackdor. Para algunos comstackdores de Windows es posible que desee probar ‘\’ en lugar de ‘/’. Incluso puede probar el sistema y configurar el delimitador en función de los resultados.

El nombre de la función es largo pero descriptivo, no hay problema. No hay forma de estar seguro de que una función devolverá un nombre de archivo, solo puede estar seguro de que puede si la función está codificada correctamente, lo que logró. Aunque si alguien lo usa en una cadena que no es una ruta, obviamente fallará. Probablemente lo habría nombrado como nombre base, ya que transmitiría a muchos progtwigdores cuál era su propósito. Esa es solo mi preferencia, aunque basado en mi sesgo tu nombre está bien. En cuanto a la longitud de la cadena, esta función manejará y ¿por qué alguien pensó que sería un punto? Es poco probable que trate con un nombre de ruta más largo de lo que esta función puede manejar en un comstackdor ANSI C. Como size_t se define como un int largo sin signo que tiene un rango de 0 a 4,294,967,295.

Probé tu función con lo siguiente.

  #include  #include  char* getFileNameFromPath(char* path); int main(int argc, char *argv[]) { char *fn; fn = getFileNameFromPath(argv[0]); printf("%s\n", fn); return 0; } char* getFileNameFromPath(char* path) { for(size_t i = strlen(path) - 1; i; i--) { if (path[i] == '/') { return &path[i+1]; } } return path; } 

Funcionó muy bien, aunque Daniel Kamil Kozar encontró un error de 1 apagado que corregí anteriormente. El error solo se mostraría con una ruta absoluta con formato incorrecto, pero aún así, la función debería poder manejar entradas falsas. No escuches a todos los que te critiquen. A algunas personas solo les gusta tener una opinión, incluso cuando no vale nada.

No me gusta la solución strstr () ya que fallará si el nombre de archivo es el mismo que el nombre de un directorio en la ruta y sí, eso puede suceder, especialmente en un sistema POSIX donde los archivos ejecutables a menudo no tienen una extensión, al menos la La primera vez, lo que significará que debe realizar varias pruebas y buscar el delimitador con strstr () es aún más engorroso, ya que no hay forma de saber cuántos delimitadores puede haber. Si se está preguntando por qué una persona querría el nombre base de un ejecutable, piense en busybox, egrep, fgrep, etc.

Strrchar () sería engorroso de implementar, ya que busca caracteres y no cadenas, por lo que no lo encuentro tan viable o conciso como esta solución. Estoy corregido por Rad Lexus, esto no sería tan engorroso como pensé, ya que strrchar () tiene el efecto secundario de devolver el índice de la cadena más allá del carácter encontrado.

Cuídate