How to extract filename from path
Or run the command » man 3 basename » on your target UNIX/POSIX system.
Use basename (which has odd corner case semantics) or do it yourself by calling strrchr(pathname, ‘/’) and treating the whole string as a basename if it does not contain a ‘/’ character.
Here’s an example of a one-liner (given char * whoami ) which illustrates the basic algorithm:
(whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]);
an additional check is needed if NULL is a possibility. Also note that this just points into the original string — a » strdup() » may be appropriate.
You could use strstr in case you are interested in the directory names too:
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);
The basename() function returns the last component of a path, which could be a folder name and not a file name. There are two versions of the basename() function: the GNU version and the POSIX version.
The GNU version can be found in string.h after you include #define _GNU_SOURCE :
#define _GNU_SOURCE #include
The GNU version uses const and does not modify the argument.
char * basename (const char *path)
This function is overridden by the XPG (POSIX) version if libgen.h is included.
This function may modify the argument by removing trailing ‘/’ bytes. The result may be different from the GNU version in this case:
will return the string «bar» if you use the XPG version and an empty string if you use the GNU version.
Of course if this is a Gnu/Linux only question then you could use the library functions.
And though some may disapprove these POSIX compliant Gnu Library functions do not use const. As library utility functions rarely do. If that is important to you I guess you will have to stick to your own functionality or maybe the following will be more to your taste?
#include #include int main(int argc, char *argv[]) < char *fn; char *input; if (argc >1) input = argv[1]; else input = argv[0]; /* handle trailing '/' e.g. 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; >
template charType* getFileNameFromPath( charType* path ) < if( path == NULL ) return NULL; charType * pFileName = path; for( charType * pCur = path; *pCur != '\0'; pCur++) < if( *pCur == '/' || *pCur == '\\' ) pFileName = pCur+1; >return pFileName; >
call: wchar_t * fileName = getFileNameFromPath < wchar_t >( filePath );
Welcome to Stack Overflow! You should note that this question was tagged c, while your answer is in c++..
You can escape slashes to backslash and use this code:
#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; >
I used a simpler way to get just the filename or last part in a path.
char * extract_file_name(char *path) < int len = strlen(path); int flag=0; printf("\nlength of %s : %d",path, len); for(int i=len-1; i>0; i--) < if(path[i]=='\\' || path[i]=='//' || path[i]=='/' ) < flag=1; path = path+i+1; break; >> return path; >
Input path = "C:/Users/me/Documents/somefile.txt" Output = "somefile.txt"
@Nikolay Khilyuk offers the best solution except.
1) Go back to using char *, there is absolutely no good reason for using const.
2) This code is not portable and is likely to fail on none POSIX systems where the / is not the file system delimiter depending on the compiler implementation. For some windows compilers you might want to test for ‘\’ instead of ‘/’. You might even test for the system and set the delimiter based on the results.
The function name is long but descriptive, no problem there. There is no way to ever be sure that a function will return a filename, you can only be sure that it can if the function is coded correctly, which you achieved. Though if someone uses it on a string that is not a path obviously it will fail. I would have probably named it basename, as it would convey to many programmers what its purpose was. That is just my preference though based on my bias your name is fine. As far as the length of the string this function will handle and why anyone thought that would be a point? You will unlikely deal with a path name longer than what this function can handle on an ANSI C compiler. As size_t is defined as a unsigned long int which has a range of 0 to 4,294,967,295.
I proofed your function with the following.
#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; >
Worked great, though Daniel Kamil Kozar did find a 1 off error that I corrected above. The error would only show with a malformed absolute path but still the function should be able to handle bogus input. Do not listen to everyone that critiques you. Some people just like to have an opinion, even when it is not worth anything.
I do not like the strstr() solution as it will fail if filename is the same as a directory name in the path and yes that can and does happen especially on a POSIX system where executable files often do not have an extension, at least the first time which will mean you have to do multiple tests and searching the delimiter with strstr() is even more cumbersome as there is no way of knowing how many delimiters there might be. If you are wondering why a person would want the basename of an executable think busybox, egrep, fgrep etc.
strrchar() would be cumbersome to implement as it searches for characters not strings so I do not find it nearly as viable or succinct as this solution. I stand corrected by Rad Lexus this would not be as cumbersome as I thought as strrchar() has the side effect of returning the index of the string beyond the character found.
How to Get Filename from the Full Path in Linux
The full path of a file in Linux refers to the complete address including directories and subdirectories using which the file can be located. Every operating system has different variants of the full path of a file.
In Linux, it looks something like the following:
This is the full file path of file test.txt.
When manually dealing with a file path, it is easy to get the filename, but if you are using a script for some kind of automation, you might need to extract the filename in certain scenarios.
Let’s see how we can extract filename out of the full path in Linux.
Using Basename Command
The whole purpose of the basename command is to retrieve filename out of a file path. Although it is not too difficult to get the filename from a full path, basename automatically does it for you and you don’t have to go through the trouble of parsing the file path, etc.
$ basename full_file_path $ basename /var/log/syslog [example command]
Use the -a an argument to pass multiple paths.
$ basename -a /var/log/syslog /var/log/dpkg.log
Using Bash Parameter Substitution
Bash Parameter Substitutions are a way to modify a variable on the fly. Hence to use this method, we need to store the file path in a variable.
Now we will apply parameter substitution and store the value in another variable.
Basically what this does is that: it shreds the part before the last ‘/’ in ‘full path’ and just keeps the rest of the string, which is nothing but the filename.
Conclusion
In this article, we learned about two ways to get a filename from a full file path in Linux. If you want to learn more about the command basename and parameter substitutions in Bash, make sure you go through their respective man pages with:
Thanks for reading and let us know your thoughts and questions below!
How to show the full path of a file or directory in the terminal?
I need to know how the directory name in order to type it out in the terminal. How do I access the names of directories? Windows Explorer used to have a title bar with the full path. Can someone please help me figure out how to see the full path of a certain file?
If you know the path and need to type it out quickly, nothing is better than Tab completion, especially with zsh .
I figured out a way to delete files with BleachBit, thanks for your answer. But for the other query I still need to know how to see the FULL path of any certain file or folder.
3 Answers 3
If you are using nautilus to browse your files, you can toggle the navigation bar by pressing Ctrl + L .
If you are using the terminal, just use pwd to know the absolute path of your current location.
And don’t forget that space characters need to be escaped within the terminal. If you want to access /path/to/the force then you need to do cd /path/to/the\ force .
To display the full path of a file in the terminal just drag the file’s icon into the terminal, and the full path of the file will be displayed enclosed by two apostrophes (single quotation mark characters). It’s that simple.
In Ubuntu 20.04 and later drag and drop of files or directories doesn’t work from the desktop, but does work in other locations including dragging from the desktop in Files file manager.
find can do this quite handily from the terminal. Here’s an example in which I’m looking for the full path of the file Taxes-2013.pdf:
sudo find / -name Taxes-2013.pdf
/home/me/Documents/Taxes-2013.pdf
I’m using sudo so that I can avoid all the permission denied output that I would otherwise get with find when searching from the root of the tree.
If you just want the pathname and want the filename stripped off you can use
sudo find / -name Taxes-2013.pdf | xargs -n1 dirname
Note: If you are in the habit of putting spaces in names this is relevant to you.
How can you quickly get the complete path to a file for use in terminal?
The downside of readlink is that it will work even if the file doesn’t exist. This can perpetuate bugs in very odd ways.
Just drag and drop the file in the terminal.
@Kupiakos: for me, gnome-terminal happily translates the dropped file path to ‘/home/alexcohn/.gvfs/…’
All good answers; Here is a tip for another situation.
If you are browsing your files using nautilus and you want the complete path of your current directory, then press CTRL+L . This changes the breadcrumb buttons temporarily back to the old-style address bar, allowing you to copy the path.
Exactly what I was looking for, I mean the terminal is a great place to ls but there is those times you work in a file folder views : ‘ )
If it’s an executable, then execute (in a terminal):
In addition to dragging the icon, there are a few ways to get the full path without nautilus (or thunar, konqueror, et al.). You would then triple-click or click-drag and copy, potentially saving this in your clipboard manager*, and paste it where you need.
(pastie, klipper, glippy, glipper, anamnesis)
- You can use find in a directory above your file. (If you don’t know where it is, start where your shell drops you, [generally] in the top of your home directory.)
find . | egrep filename - You can use locate to get the filename. (Run sudo updatedb if that hasn’t been done recently.)
A more realistic example of using find would be something like :
$ find | egrep askubuntu | grep txt ./askubuntu-temp.txt ./drDocuments/web/meta.askubuntu.txt ./other/stuff/askubuntu.txt.iteration.1 ./other/stuff/askubuntu.txt.iteration.2 [. ]
To cut out the ones you don’t like, e.g.:
find | egrep askubuntu | grep txt | egrep -v iteration find | egrep askubuntu | grep txt | egrep -v 'iteration|meta|other'
locate is used much the same way, though grep is frequently more necessary:
locate myfile | egrep home | egrep -v 'mozilla|cache|local|bin|\.pyc|test' | grep \.py
This isn’t the most efficient way to type this, but usually if I’ve lost a file, I do this iteratively, adding grep clauses as I go.