Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / Mac Programming / March 2008



Tip: Looking for answers? Try searching our database.

Quick NSString question

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
jim - 11 Mar 2008 08:15 GMT
If I've got an NSString that contains a filename (including the path),
what's the best way of adding quotation marks to the beginnng and end?

In other words I'd like to convert:

/users/jim/file.ext

to

"/users/jim/file.ext"

I need to do this for passing it as an argument to a command-line util,
and it won't work as-is if there are spaces in the filename or path.

Many thanks.

Jim
Signature

"I need a dry run with the custard." - SWMBO.

Find me at http://www.UrsaMinorBeta.co.uk

Gregory Weston - 11 Mar 2008 09:18 GMT
> If I've got an NSString that contains a filename (including the path),
> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 9 lines]
> I need to do this for passing it as an argument to a command-line util,
> and it won't work as-is if there are spaces in the filename or path.

The best option, under "Working with Paths" in the list of tasks in the
NSString docs, is to use the method named fileSystemRepresentation.

That should reliable perform whatever escaping is required by your
current file system(s). There's potentially more to cleaning up an
arbitrary NSString than just dealing with spaces.
Jim - 11 Mar 2008 09:39 GMT
>> If I've got an NSString that contains a filename (including the path),
>> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 16 lines]
> current file system(s). There's potentially more to cleaning up an
> arbitrary NSString than just dealing with spaces.

Thank you, I'll give that a read.

Rather surprised with myself for missing it the first time...

Jim
Signature

http://www.ursaMinorBeta.co.uk
"When one of the local cats, an especially fluffy creature with a vast
tail, rushed down the street towards me the other day, mewing delightedly,
I have to admit it was probably shouting 'HAZ CHEZBURGR?' " - Bella, ucsm

David Phillip Oster - 11 Mar 2008 15:26 GMT
> > If I've got an NSString that contains a filename (including the path),
> > what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 16 lines]
> current file system(s). There's potentially more to cleaning up an
> arbitrary NSString than just dealing with spaces.

That is necessary, but not sufficient. Remember that the original poster
is passing it to some command line utility. If he does that with
system() or popen(), [path fileSystemRepresentation] is just the first
step. He'll still need to do additional quoting the quote character, and
the character he uses to do that. But that still isn't enough, because
of dollar-sign substitution and backquote subshells.

a file name subject to dollar-sign substitution:  

foo$PATH

a file name subject to:backquote subshell:

foo `echo hello`

so, you need to:

NSString *path = [path fileSystemRepresentation];
NSString *quotedPath = [[path s:@"\\" r:@"\\\\"] s:@"'" r:@"\\'"];

(remember that you have to escape the '\' character in Obj-C)
Single-quote quoting tells the shell not to evaluate subshells or do
dollar-sign substitution, so our examples become: 'foo$PATH' and 'foo
`echo hello`'

where you've defined the -s:r: method as

@interface NSString(MyMethods)
// search for all occurrences of search substring, and replace each.
- (NSString *)s:(NSString *)search r:(NSString *)replace;
@end

In 10.5, there is the handy NSString method:

- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target
withString:(NSString *)replacement;

which does the -s:r: job, but in 10.4 you'll need to write it. It can be
simply written as

return [[self componentsSeparatedByString:search]
componentsJoinedByString:replace];
Ben Artin - 11 Mar 2008 15:06 GMT
> If I've got an NSString that contains a filename (including the path),
> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 9 lines]
> I need to do this for passing it as an argument to a command-line util,
> and it won't work as-is if there are spaces in the filename or path.

Don't. If you are doing that, you are calling the command-line util incorrectly
-- probably, you are calling it through the shell (using system() or a wrapper
around it), which will also perform various other substitutions that will break
your code.

Instead, you should be using a different API for running the command line util
-- either fork() and exec() directly, or some wrapper around them. Those require
no quoting or other shenanigans.

Ben

Signature

If this message helped you, consider buying an item
from my wish list: <http://artins.org/ben/wishlist>

Jim - 14 Mar 2008 08:06 GMT
> Instead, you should be using a different API for running the command line
> util -- either fork() and exec() directly, or some wrapper around them.
> Those require no quoting or other shenanigans.

The general advice seems to be to re-code using NSTask(), which is what
I'm going to do when I've shifted the Head Cold From Hell.

Jim
Signature

'Cloverfield' in nine words: "What is it?!" "We're gonna die!" BOOM!
Roll credits.

Find me at http://www.ursaminorbeta.co.uk

glenn andreas - 11 Mar 2008 15:34 GMT
> If I've got an NSString that contains a filename (including the path),
> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 9 lines]
> I need to do this for passing it as an argument to a command-line util,
> and it won't work as-is if there are spaces in the filename or path.

If you use NSTask to invoke the utility, you don't need to any of the
escape/quote stuff (since you pass each argument as a separate item in
an array, as opposed to having a shell see the entire thing as one line
and having to figure out where each argument is).
jim - 12 Mar 2008 08:15 GMT
> If I've got an NSString that contains a filename (including the path),
> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 9 lines]
> I need to do this for passing it as an argument to a command-line util,
> and it won't work as-is if there are spaces in the filename or path.

Thanks for the replies - I got around it by simply adding some /" into
the filenames. Since the full path/filename is coming from the
pasteboard would I be correct in assuming it's essentially going to be a
'valid' filename to begin with, and simply adding the /" is the way to
go? Or should I be a lot more strict?

Essentially I've done this:

----------
NSMutableString *command = [[NSMutableString alloc]
initWithString:(NSString *)@"uuencode "];

if (mFlag)
{
       [command appendString:@"-m -o \""];
}
else
{
       [command appendString:@"-o \""];
}
       
       
[command appendString:newFileName];
[command appendString:@"\" \""];
[command appendString:fileName];
[command appendString:@"\" disc0.ssd"];

char *commandToRun = (char *)[command
cStringUsingEncoding:(NSStringEncoding)NSASCIIStringEncoding];

//NSLog(@"commandToRun = %s", commandToRun);
system( commandToRun );

[newFileName release];
----------

where 'fileName' is passed in as an argument and comes from a
drag'n'dropped pasteboard array item.

Jim
Signature

"I need a dry run with the custard." - SWMBO.

Find me at http://www.UrsaMinorBeta.co.uk

David Phillip Oster - 12 Mar 2008 08:50 GMT
> > If I've got an NSString that contains a filename (including the path),
> > what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 50 lines]
>
> Jim

Glenn Andreas had the best suggestion: don't use system(), since you'll
get into the quoting problems I described. Instead use [NSTask
launchedTaskWithLaunchPath: arguments: ]

Note that you the array of file paths that you get from a drag is
exactly what this wants for arguments: -  it will take care of calling
fileSystemRepresentation so the character set encoding issues between
NSString and the BSD layer will be handled correctly for you.

Thanks Glenn.
-- David Phillip Oster
Jim - 12 Mar 2008 09:30 GMT
> Glenn Andreas had the best suggestion: don't use system(), since you'll
> get into the quoting problems I described. Instead use [NSTask
[quoted text clipped - 4 lines]
> fileSystemRepresentation so the character set encoding issues between
> NSString and the BSD layer will be handled correctly for you.

Right-o, I'll do some reading on that.

Thanks.

Jim
Signature

http://www.ursaMinorBeta.co.uk
"When one of the local cats, an especially fluffy creature with a vast
tail, rushed down the street towards me the other day, mewing delightedly,
I have to admit it was probably shouting 'HAZ CHEZBURGR?' " - Bella, ucsm

Jim - 12 Mar 2008 09:53 GMT
>> Glenn Andreas had the best suggestion: don't use system(), since you'll
>> get into the quoting problems I described. Instead use [NSTask
[quoted text clipped - 6 lines]
>
> Right-o, I'll do some reading on that.

[self doABitOfReading];

Yep, that looks exactly like what I should be using. I'll re-code over the
weekend.

Jim
Signature

http://www.ursaMinorBeta.co.uk
"When one of the local cats, an especially fluffy creature with a vast
tail, rushed down the street towards me the other day, mewing delightedly,
I have to admit it was probably shouting 'HAZ CHEZBURGR?' " - Bella, ucsm

Jim - 12 Mar 2008 09:58 GMT
>>> Glenn Andreas had the best suggestion: don't use system(), since you'll
>>> get into the quoting problems I described. Instead use [NSTask
[quoted text clipped - 11 lines]
> Yep, that looks exactly like what I should be using. I'll re-code over the
> weekend.

Incidentally, that last line of code

[newFilename release];

was it required? As newFilename is created within that function, would it
be automatically released at the end? And if so, is there a problem with me
explicitly releasing it?

Is there perhaps a 'dummies guide to object management' that someone could
aim me at?

Thank you.

Jim
Signature

http://www.ursaMinorBeta.co.uk
"When one of the local cats, an especially fluffy creature with a vast
tail, rushed down the street towards me the other day, mewing delightedly,
I have to admit it was probably shouting 'HAZ CHEZBURGR?' " - Bella, ucsm

David Phillip Oster - 13 Mar 2008 02:37 GMT
>> Incidentally, that last line of code
>
[quoted text clipped - 6 lines]
> Is there perhaps a 'dummies guide to object management' that someone could
> aim me at?

well, I can't tell, since the line where newFile was created wasn't in
the postings I read.

If you did:

NSString *newFile = [someOtherString copy];

then you do need to release it. If you did:

NSString *newFile = [someOtherString subStringFromIndex:12];

then you don't.

I've gotten in the habit of writing:

NSString *newFile = [[someOtherString copy] autorelease];

for my [copy]s and [init]s,

just so I don't have to worry about [release]s getting mis-paired as the
code is maintained.
jim - 13 Mar 2008 07:11 GMT
> well, I can't tell, since the line where newFile was created wasn't in
> the postings I read.

Oh, bother - sorry, the coffee hadn't hit my blood stream at that point.

It's created thusly:

NSMutableString *newFileName = [[NSMutableString alloc]
initWithString:fileName];

Jim
Signature

"I need a dry run with the custard." - SWMBO.

Find me at http://www.UrsaMinorBeta.co.uk

Jim - 13 Mar 2008 08:02 GMT
> > well, I can't tell, since the line where newFile was created wasn't in
> > the postings I read.
[quoted text clipped - 5 lines]
> NSMutableString *newFileName = [[NSMutableString alloc]
> initWithString:fileName];

And I've just realised I need a [command release] at the bottom as well.

Jim
Signature

'Cloverfield' in nine words: "What is it?!" "We're gonna die!" BOOM!
Roll credits.

Find me at http://www.ursaminorbeta.co.uk

Sherman Pendley - 25 Mar 2008 15:12 GMT
> If I've got an NSString that contains a filename (including the path),
> what's the best way of adding quotation marks to the beginnng and end?
[quoted text clipped - 6 lines]
>
> "/users/jim/file.ext"

NSString *newString = [NSString stringWithFormat:@"\"%@\"", oldString];

> I need to do this for passing it as an argument to a command-line util,
> and it won't work as-is if there are spaces in the filename or path.

Are you sure about that? If you're passing this as part of a command that
will be interpreted by a shell, then yes, that shell needs paths to be
quoted. But APIs like NSTask or system() don't care about spaces, because
their arguments are passed directly as arrays - they're not trying to parse
a command string that uses spaces between arguments.

sherm--

Signature

My blog: http://shermspace.blogspot.com
Cocoa programming in Perl: http://camelbones.sourceforge.net

 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.