Here's a simple file path plain-C routine which should programmatically expand tildes and accept whitespaces as legitimate characters in file names. It works fine with names such as:
~/Test Folder/test.txt
/Users/Shared/Test Folder/test.txt
but does not seem to work with path syntax as suggested by Apple or as generated by Terminal.app if drag&dropping file's icon to the Terminal.app's window:
/Users/Shared/Test\ Folder/test.txt
or
~/Test\ Folder/test.txt
Here's the code. I'm obviously missing the routine which would substitute 'escaped whitespace' for 'plain whitespace' characters. On the other hand, any search routine for '\ ' results in compiler complaints about "unknown escape sequence" 0x20 (which btw. seems to be the valid whitespace code in some unix and linux systems, possibly not in OSX?).
Is there a solution to the problem within plain-C and C-strings, without having to deal with Apple's proprietary CFStrings and NSStrings, where I know that solutions are simple? I just can't afford using any of those in this program. Also no shell scripts, ruby, gawk, grep, perl, python, etc..., please.
Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wordexp.h>
void get_file_path(char path[])
{
char *p;
size_t len = 0;
wordexp_t exp_result;
printf("Enter file name: \n");
p = fgets(path, TEXT_SIZE, stdin);
fflush(stdin);
if(p != NULL)len = strlen(path);
//get rid of newline characters
for(p = path; p < path + len; p++){
if(*p == '\n') *p = '\0';
}
if(path[0] == '~'){
wordexp(path, &exp_result, 0);
//printf("Num.expansions: %zd\n", exp_result.we_wordc);
strcpy(path, exp_result.we_wordv[0]);
for(size_t i = 1; i < exp_result.we_wordc; i++){
//printf("%s\n", exp_result.we_wordv[i]);
strcat(path, " ");
strcat(path, exp_result.we_wordv[i]);
}
wordfree(&exp_result);
}
printf("File path: %s\n", path);
return;
}
Here's the shell output:
Enter file name:
/Users/Shared/Test\ Folder/test.txt
File path: /Users/Shared/Test\ Folder/test.txt
Can't open file: /Users/Shared/Test\ Folder/test.txt
This is not an answer to the main issue with code, but it is a problem with the code.
if(path[0] == '~'){
is a subtle problem.
p = fgets(path, TEXT_SIZE, stdin);
...
if(path[0] == '~'){
When p == NULL
the content of path
is not define on IO error and likely the previous buffer contents when EOF
occurs. Better to change return type from void
to char *
, and return when p == NULL
.
p = fgets(path, TEXT_SIZE, stdin);
if (p == NULL) {
return NULL;
}