Quick NSString question
|
|
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
|
|
|