473,888 Members | 1,426 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Getting path components

Has anyone got a code snippet to separate out the path components, ie drive,
path, filename, and extension ?

Many thanks in advance,

Aaron
Jun 27 '08 #1
18 3527
In article <67************ *@mid.individua l.net>,
Aaron Gray <an********@gma il.comwrote:
>Has anyone got a code snippet to separate out the path components, ie drive,
path, filename, and extension ?
No, there is no portable way to do that.

Standard C does not place any interpretation upon filenames
passed to the Standard I/O library functions, and has no idea
what a "drive", "path", or "extension" is. Standard C also has
no idea of what character or characters are used to seperate
the various components, including having no opinion on the very
existance of directories let alone the directory seperator.

Furthermore, with Microsoft's NTFS filesystem, the old drive lettering
system is superceeded, and drive names there can look like directory
names; NTFS also supports virtual mount points, so what -looks- like
a file X in directory Y might in fact be program Y with
command argument X. This use of Alternate Data Streams is not
distinguished in any syntactic way.

There are valid Unix file names that look -exactly- the same
as some valid MS Windows file names, and yet have completely
different interpretation. Then there's openVMS, and MVS, and lots
of other strange filesystem naming schemes. Oh yes and remember
that in MacOS (before MacOS X) that ':' was the directory seperator...
--
"There is no greater calling than to serve your fellow men.
There is no greater contribution than to help the weak.
There is no greater satisfaction than to have done it well."
-- Walter Reuther
Jun 27 '08 #2
On 21 Apr 2008 at 16:34, Aaron Gray wrote:
Has anyone got a code snippet to separate out the path components, ie drive,
path, filename, and extension ?
With POSIX, you can use dirname() and basename() in combination. There's
also realpath() if you need it.

I don't know what the equivalent functions are on MS-Windows - maybe
jacob navia will drop in with the answer.

Jun 27 '08 #3
"Antoninus Twink" <no****@nospam. invalidwrote in message
news:sl******** ***********@nos pam.invalid...
On 21 Apr 2008 at 16:34, Aaron Gray wrote:
>Has anyone got a code snippet to separate out the path components, ie
drive,
path, filename, and extension ?

With POSIX, you can use dirname() and basename() in combination. There's
also realpath() if you need it.

I don't know what the equivalent functions are on MS-Windows - maybe
jacob navia will drop in with the answer.
basename.c from BSD :-

http://www.krugle.org/kse/files?query=basename#3

is just :-

strrchr(path, '/')

basename from OpenSSH :-

http://www.krugle.org/kse/codespaces/DXRo7v

dirname from OpenSSH :-

http://www.krugle.org/kse/codespaces/B4cBVF

realpath from OpenSSH :-

http://www.krugle.org/kse/codespaces/Cn10Ja

Should be nice and secure :)

Thanks,

Aaron
Aaron
Jun 27 '08 #4
In article <sl************ *******@nospam. invalid>,
Antoninus Twink <no****@nospam. invalidwrote:
>On 21 Apr 2008 at 16:34, Aaron Gray wrote:
>Has anyone got a code snippet to separate out the path components, ie drive,
path, filename, and extension ?
>With POSIX, you can use dirname() and basename() in combination. There's
also realpath() if you need it.
Those are not part of POSIX.1-1990; they were not added until
Single Unix Specification Issue 4, Version 2, and were not
moved from X/OPEN UNIX extension to BASE until Issue 5 (in 2002, I think,
but I'm not sure.)
--
"I buy more from my grocer than he buys from me, and I bet it's
the same with you and your grocer. That means we have a trade
deficit with our grocers. Does our perpetual grocer trade deficit
portend doom?" -- Walter Williams
Jun 27 '08 #5
In article <67************ *@mid.individua l.net>,
Aaron Gray <an********@gma il.comwrote:
>"Antoninus Twink" <no****@nospam. invalidwrote in message
news:sl******* ************@no spam.invalid...
>On 21 Apr 2008 at 16:34, Aaron Gray wrote:
>>Has anyone got a code snippet to separate out the path components, ie
drive,
path, filename, and extension ?
>basename.c from BSD :-
basename from OpenSSH :-
dirname from OpenSSH :-
realpath from OpenSSH :-
And which one of those returns the 'drive' as per the original
requirements?

>basename.c from BSD :-
http://www.krugle.org/kse/files?query=basename#3
>is just :-
strrchr(path, '/')

That fails the follow the POSIX requirements.

http://www.opengroup.org/onlinepubs/.../basename.html

and consider how the quoted code would behave on the example
"//usr//lib//"
--
"Every intellectual product must be judged from the point of view
of the age and the people in which it was produced."
-- Walter Horatio Pater
Jun 27 '08 #6

"Aaron Gray" <an********@gma il.comwrote in message
news:67******** *****@mid.indiv idual.net...
Has anyone got a code snippet to separate out the path components, ie
drive, path, filename, and extension ?
If on Windows, I think there are the Path functions in the Windows Shell
(although I've never used them).

But code to parse a filespec isn't that difficult. I put together some code
below which may or may not be useful. It doesn't extract drive letters,
that's considered part of the path.

This may be specific to Windows of course and probably won't work for
anything else or for network/internet paths.

#include <stdio.h>
#include <string.h>

/* Extract only the path from a filespec */
/* All dest parameters here must point to a string at least the same length
as fs */
void extractpath(cha r *fs, char *dest) {
int l=strlen(fs),i;

*dest=0;

for (i=l; i>=1; --i)
if (fs[i-1]=='\\' || fs[i-1]=='/') {
strcpy(dest,fs) ;
dest[i]=0;
return;
};
return;
}

/* Extract a full filename including extension */
void extractfile(cha r *fs, char *dest) {
int a,b;

extractpath(fs, dest); /* start with path */

a=strlen(fs);
b=strlen(dest);

if (b>=a) return; /* no file? */

/* return the a-b chars at the end of fs */
strcpy(dest,fs+ b);
}

/* Extract the extension only. Period = 0 or 1 to return a null extension as
"" or "." */
void extractext(char *fs,char *dest,int period) {
int i,n;

extractfile(fs, dest);
n=strlen(dest);
if (!n) return; /* no file so no ext */

/* look for right-most period */

for (i=n; i>=1; --i)
if (dest[i-1]=='.') {
strcpy(dest,des t+i); /* possible overlap copy */
if (*dest==0 && period) {
strcpy(dest,"." );
return;
};
return;
};

/* no period in file */
*dest=0;
if (period)
strcpy(dest,"." );
return;
}

/* Extract the filename excluding the extension, and with no trailing period
*/
void extractbasefile (char *fs, char *dest) {
int a,b;

extractext(fs,d est,0);
a=strlen(dest); /* chars in extension */

extractfile(fs, dest); /* filename with extension */
b=strlen(dest)-a; /* chars in file w/o ext */

dest[b]=0; /* exclude extension */

if (dest[b-1]=='.') dest[b-1]=0; /* avoid trailing period */
}

/* MAIN() */
int main(void) {
char filespec[300];
char path[300];
char file[300];
char basefile[300];
char ext[300];

strcpy(filespec ,"C:\\ABC\\DEF\ \GHI.JKL");

extractpath(fil espec,path);
extractfile(fil espec,file);
extractbasefile (filespec,basef ile);
extractext(file spec,ext,0);

printf("File spec = %s\n",filespec) ;
printf("Path = %s\n",path);
printf("File = %s\n",file);
printf("Basefil e = %s\n",basefile) ;
printf("Ext = %s\n",ext);

}

--
Bartc


Jun 27 '08 #7
In article <1L************ *****@text.news .virginmedia.co m>,
Bartc <bc@freeuk.comw rote:
>"Aaron Gray" <an********@gma il.comwrote in message
news:67******* ******@mid.indi vidual.net...
>Has anyone got a code snippet to separate out the path components, ie
drive, path, filename, and extension ?
>But code to parse a filespec isn't that difficult. I put together some code
below which may or may not be useful. It doesn't extract drive letters,
that's considered part of the path.
Where is the check for leading // ? In POSIX, starting a path with
exactly two / has an implementation defined result for the *entire*
path, but if there are three or more / at the beginning of the path,
then all of them are to be collapsed to a single / .

If your code doesn't handle leading / on paths according to POSIX rules
then it isn't portable to POSIX systems. And since the behaviour
for // is implementation defined, no portable code using only C standard
libraries can determine the proper system behaviour for // .
So contrary to your assertion, code to parse a filespec is not just
difficult but impossible using only standard C.

Remember: the original poster did not specify a target OS, so the
question was a generalized one about parsing *all* possible filenames
on *all* hosted systems that C exists on.
--
"Any sufficiently advanced bug is indistinguishab le from a feature."
-- Rich Kulawiec
Jun 27 '08 #8
"Bartc" <bc@freeuk.comw rote in message
news:1L******** *********@text. news.virginmedi a.com...
>
"Aaron Gray" <an********@gma il.comwrote in message
news:67******** *****@mid.indiv idual.net...
>Has anyone got a code snippet to separate out the path components, ie
drive, path, filename, and extension ?
If on Windows, I think there are the Path functions in the Windows Shell
(although I've never used them).

But code to parse a filespec isn't that difficult. I put together some
code
below which may or may not be useful. It doesn't extract drive letters,
that's considered part of the path.

This may be specific to Windows of course and probably won't work for
anything else or for network/internet paths.

#include <stdio.h>
#include <string.h>

/* Extract only the path from a filespec */
/* All dest parameters here must point to a string at least the same
length
as fs */
void extractpath(cha r *fs, char *dest) {
int l=strlen(fs),i;

*dest=0;

for (i=l; i>=1; --i)
if (fs[i-1]=='\\' || fs[i-1]=='/') {
strcpy(dest,fs) ;
dest[i]=0;
return;
};
return;
}

/* Extract a full filename including extension */
void extractfile(cha r *fs, char *dest) {
int a,b;

extractpath(fs, dest); /* start with path */

a=strlen(fs);
b=strlen(dest);

if (b>=a) return; /* no file? */

/* return the a-b chars at the end of fs */
strcpy(dest,fs+ b);
}

/* Extract the extension only. Period = 0 or 1 to return a null extension
as
"" or "." */
void extractext(char *fs,char *dest,int period) {
int i,n;

extractfile(fs, dest);
n=strlen(dest);
if (!n) return; /* no file so no ext */

/* look for right-most period */

for (i=n; i>=1; --i)
if (dest[i-1]=='.') {
strcpy(dest,des t+i); /* possible overlap copy */
if (*dest==0 && period) {
strcpy(dest,"." );
return;
};
return;
};

/* no period in file */
*dest=0;
if (period)
strcpy(dest,"." );
return;
}

/* Extract the filename excluding the extension, and with no trailing
period
*/
void extractbasefile (char *fs, char *dest) {
int a,b;

extractext(fs,d est,0);
a=strlen(dest); /* chars in extension */

extractfile(fs, dest); /* filename with extension */
b=strlen(dest)-a; /* chars in file w/o ext */

dest[b]=0; /* exclude extension */

if (dest[b-1]=='.') dest[b-1]=0; /* avoid trailing period */
}

/* MAIN() */
int main(void) {
char filespec[300];
char path[300];
char file[300];
char basefile[300];
char ext[300];

strcpy(filespec ,"C:\\ABC\\DEF\ \GHI.JKL");

extractpath(fil espec,path);
extractfile(fil espec,file);
extractbasefile (filespec,basef ile);
extractext(file spec,ext,0);

printf("File spec = %s\n",filespec) ;
printf("Path = %s\n",path);
printf("File = %s\n",file);
printf("Basefil e = %s\n",basefile) ;
printf("Ext = %s\n",ext);

}
Sorry Bartc, I go with the OpenSSH code, its ben tested properly as part of
a secure application.

Drive does not really matter for what I need, I just wrote that for
completeness.

Aaron
Jun 27 '08 #9
On Apr 21, 5:58*pm, "Bartc" <b...@freeuk.co mwrote:
"Aaron Gray" <ang.use...@gma il.comwrote in message

news:67******** *****@mid.indiv idual.net...Has anyone got a code snippet to separate out the path components, ie
drive, path, filename, and extension ?

If on Windows, I think there are the Path functions in the Windows Shell
(although I've never used them).

But code to parse a filespec isn't that difficult. I put together some code
below which may or may not be useful. It doesn't extract drive letters,
that's considered part of the path.

This may be specific to Windows of course and probably won't work for
anything else or for network/internet paths.

#include <stdio.h>
#include <string.h>

/* Extract only the path from a filespec */
/* All dest parameters here must point to a string at least the same length
as fs */
void extractpath(cha r *fs, char *dest) {
int l=strlen(fs),i;

*dest=0;

for (i=l; i>=1; --i)
* if (fs[i-1]=='\\' || fs[i-1]=='/') {
For some file systems, '\' is a valid part of a filename (as opposed
to a separator).
For some file systems, '/' is a valid part of a filename (as opposed
to a separator).
For *either* file system, this loop will misinterpret the character
that is not a separator as a separator.
On OpenVMS, the separator is '.' and paths start with a drive or
symbol, followed by colon, followed by '[' and ending with ']' before
the file name.
* * strcpy(dest,fs) ;
* * dest[i]=0;
* * return;
* };
return;

}
[snip]

Relatively portable solutions to problems of this nature are found in
SFL:
http://legacy.imatix.com/html/sfl/
see: strip_file_path (), strip_file_name (), file_is_directo ry()

and ACE:
http://www.cs.wustl.edu/~schmidt/ACE.html
See: basename()
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
1738
by: Ian Bicking | last post by:
I think Jason Orendorff's path module is really nice: http://www.jorendorff.com/articles/python/path/ Beats the hell out of os.path, which is an ugly thing indeed. The OO interface means you could use the interface nicely to implement other things, like URLs. The problem? It's just some module. The various os functions (of which path replaces quite a few) have become idiomatic to me, and I'm sure others as well. I find myself...
2
1646
by: Scott Lyon | last post by:
The error message that I'm getting is: "Cannot find the file 'C:\text.xml' (or one of its components). Make sure the path and filename are correct and that all required libraries are available". I've attached the file that I have saved at C:\text.xml. It's a simple XML file that I threw together for testing. But it's giving me that error. Does anyone have any idea why I might be getting this, and (more
3
3098
by: Hitesh | last post by:
Hi, I am getting the response from another Website by using the HttpHandler in my current site. I am getting the page but all the images on that page are not appearing only placeholder are displayed. Can anybody know this issue and help me to resolve this. In past i received the response saying that i should download the image first and then parse the actual response and modify the src attribute of the
1
3612
by: Steve | last post by:
I have been trying to find documentation on the behavior Can anyone tell me why the first example works and the second doesn't and where I can read about it in the language reference? Steve print os.path.join(os.path.dirname(os.tmpnam()),*("a","b","c")) #works OUTPUT:/var/tmp/a/b/c and
6
21386
by: Lubomir | last post by:
Hi, Where in .NET are definded constants for maximal file name length and maximal file path? Thanks, Lubomir
10
11808
by: Elliot Peele | last post by:
Why does os.path.join('/foo', '/bar') return '/bar' rather than '/foo/bar'? That just seems rather counter intuitive. Elliot
3
5271
by: moongirl | last post by:
Part of an application I am building includes a button which the user can click on to view a PDF file in Acrobat Reader, using the following code: System.Diagnostics.Process.Start(@"C:\Program Files \Adobe\Reader 8.0\Reader\AcroRd32.exe", @PDFfilePath); However the path to acrobat reader is the path on my PC - what if the path is different on the user's PC? How can I change the code to find
33
11888
by: JamesB | last post by:
I am writing a service that monitors when a particular app is started. Works, but I need to get the user who is currently logged in, and of course Environment.UserName returns the service logon (NT_AUTHORITY\SYSTEM). I understand that when the service starts, no user may be logged in, but that's ok, as the app I am monitoring can only be run by a logged in user. Do I need to use WMI to get the user context of Explorer.exe or is there a...
8
1995
by: eliben | last post by:
Hello, os.path.split returns the head and tail of a path, but what if I want to have all the components ? I could not find a portable way to do this in the standard library, so I've concocted the following function. It uses os.path.split to be portable, at the expense of efficiency. ---------------------------------- def parse_path(path):
0
11181
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10886
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10439
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9597
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7990
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6014
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4642
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4245
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3252
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.