Reputation: 7142
I have to open some file for writing, and its name contains the tilde sign (~
). The following code fails to create the desired text file. If I replace the ~
with /home/oren
then everything works fine.
#include <fstream>
#include <string>
const std::string dirname = "/home/oren/GIT/";
// const std::string dirname = "~/GIT/";
const std::string filename = "someTextFile";
int main(int argc, char **argv)
{
std::ofstream log_file(dirname+filename+".txt");
log_file << "lorem ipsum";
log_file.close();
}
Is there any way to (easily) handle a file with ~
in its name?
Upvotes: 7
Views: 4531
Reputation: 238371
The tilde is expanded to the home directory by the shell. The iostreams don't use a shell, so you have to take care of the expansion for them. Tilde is a actually a valid character to use in a file name so without expansion, a file is created into a directory named ~
- which fails if the directory does not exist.
There is no standard way in C++ for shell expansions, nor a way to get the home directory, but there are several ways in POSIX systems:
wordexp
is probably one of the most useful functions for this case. You can pass the path to the function and it will expand the tilde, as well as variables and braces. An example:
std::string full = dirname+filename+".txt"
wordexp_t p;
wordexp(full.c_str(), &p, 0);
std::string expanded = p.we_wordv[p.we_offs];
wordfree(&p);
std::ofstream log_file(expanded);
Other alternatives:
getpwuid
gives you a structure with the home directory as a member. This can be used to get home directory of another user as well, in case that is needed.
HOME
environment variable should also be available. It can be accessed with the standard std::getenv
.
Upvotes: 2
Reputation: 19118
The ~
shortcut in paths is not something magical at the filesystem level, opening ~/GIT
literally tries to access ~/GIT
, i.e: a file named GIT
in the ~
directory. You can verify this by creating ~
and GIT
first.
In the command line, ~
is typically resolved by your shell. e.g: in bash:
~ : The value of $HOME
https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
Therefore, to achieve the same effect, you have to query the $HOME
envvar, and replace the usage of leading ~/
in the path:
#include <stdlib.h>
const char* home = getenv("HOME")
if (home) { /* replace ~/ with home */ }
In addition, on linux, the wordexp function can be used to perform these replacements (~ to current user, ~other_user to home of other user)
Upvotes: 19
Reputation: 409216
The tilde is part of the shell expansion, it's not something handled by the underlying operating system. You need to resolve it yourself.
One simple way is to replace leading "~/"
with the contents of the environment variable HOME
(if it exists).
Upvotes: 5