How to create a folder outside the poject directory in rust - rust

I using rust to create a folder in ~, however when my code runs the directory is created inside my project's folder instead in ~.
My code:
use std::fs::create_dir_all;
use std::path::Path;
fn main() {
let path = Path::new("~/.hidden_folder");
match create_dir_all(path) {
Ok(f) => {
println!("created folder")
},
Err(err) => {
println!("{:?}", err);
}
};
}
Any idea how to create the folder in the correct directory ?

If you want your home directory, I recommend using this crate or specifying the absolute path. If you want to save it in any other directories, just use relative or absolute paths, but don't use ~ because Rust doesn't know the context of ~.

Related

What is the best way to check if an executable exists for `std::process::Command`?

I want to create a std::process::Command and check whether an executable actually exists at that location before actually spawning the Command later. What would be the pragmatic way to do this?
I have this code:
let c = std::process::Command::new("my_exe");
// something here
c.spawn().unwrap();
I want to be able to validate the my_exe path when creating the Command and then spawn way later.
check whether an executable actually exists at that location before actually spawning the Command.
Don't as that's a time-of-check to time-of-use race condition. Instead, check the error value from executing the Command: Check if a command is in PATH/executable as process.
If you want to check if a file is present in the working directory, you can use Path::exists, as described in How to check whether a path exists?.
Also, Command::spawn() takes a mutable reference to self so c needs to be mutable.
use std::path::Path;
use std::process::Command;
if Path::new("PATH_TO_EXECUTABLE").exists() {
let mut c = Command::new("PATH_TO_EXECUTABLE");
// do something
c.spawn().unwrap();
}
Use the is_executable crate:
use is_executable::IsExecutable;
use std::fs;
let paths = fs::read_dir("./").unwrap();
for path in paths {
let file_path = path.unwrap().path();
if file_path.is_executable() {
println!("File: {:?} is executable!", file_path);
} else {
println!("File: {:?} is _not_ executable!", file_path);
}
}

Is it possible to access current file name?

Is it possible to access current file name in Rust by
// main.rs
fn main() {
println!("filename: {}", FILE_NAME);
}
?
(This program should print filename: main.rs)
You can use the std::file macro to get the current source filename at the compile time.
let this_file = file!();
If you want to remove the path from the returned filename, you can construct a Path with it and call the file_name method.
let filename_only = Path::new(this_file).file_name().and_then(|s| s.to_str()).unwrap();
Playground

Rust build script to copy a file to target directory

For my project, I would like to copy the file config.ron that is in the root of my project to the target directory when the project is built. I know that you can use include_str! to add the content of the file to the program at compile time, but I would like the file to stay in the root of the target folder so that it can be edited without the need to recompile the program.
I've currently been trying out a build script to accomplish this but I am have no luck.
use std::process::Command;
use std::env;
fn main() {
let profile = std::env::var("PROFILE").unwrap();
match profile.as_str() {
"debug" => {
Command::new("cmd")
.args(&["copy", "/y"])
.arg(&format!(r#"{}\config.ron"#, env::var("CARGO_MANIFEST_DIR").unwrap()))
.arg(&format!(r#"{}\target\debug"#, env::var("CARGO_MANIFEST_DIR").unwrap()))
.status()
.expect("Copy failed to execute.");
()
},
"release" => {
Command::new("cmd")
.args(&["copy", "/y"])
.arg(&format!(r#"{}\config.ron"#, env::var("CARGO_MANIFEST_DIR").unwrap()))
.arg(&format!(r#"{}\target\release"#, env::var("CARGO_MANIFEST_DIR").unwrap()))
.status()
.expect("Copy failed to execute.");
()
},
_ => (),
}
}
What would be the correct way to get this file copied to the target directory using a build script?
If you really want to do it in a build script, I would go with these ingredients:
OUT_DIR and CARGO_TARGET_DIR
std::fs::copy

Inconsistent behavior of `mktemp` crate in Rust

If I call .to_path_buf() immediately after expect, the temporary directory will not be created. Is this a bug or a Rust feature?
extern crate mktemp;
use std::path::Path;
fn main() {
let temp_dir = mktemp::Temp::new_dir().expect("Failed to create a temp directory");
let temp_dir_path = temp_dir.to_path_buf();
println!("tmp path exists: {}", Path::exists(&temp_dir_path));
let temp_dir_path = mktemp::Temp::new_dir().expect("Failed to create a temp directory").to_path_buf();
println!("tmp path exists: {}", Path::exists(&temp_dir_path));
}
Which outputs:
tmp path exists: true
tmp path exists: false
I don't know, but I wonder if there's something in the mktemp documentation about this...
Once the variable goes out of scope, the underlying file system resource is removed.
You're not storing the Temp in a variable, so it goes out of scope immediately. It's creating the directory and then immediately destroying it.

File and folders create if not exist

Is there anything like fs.create(path) that if path not exist then create it.
For example, fs.Create('D:/test/a.txt') and it will create test folder and a.txt file if a.txt not exist.
I know how to create the file if not exist but how about folder's'?
I think it is a simple problem. Does any lib can do that? Or I need to parse the path and create it?
If you don't want to add dependencies the following may work for you, where dirPath is an array of the path segments you want to mkdirsync to:
let dirPath = [cwd, `..`, `..`, `folderA`, `folderB`]
let outDir = []
dirPath.forEach(element => {
outDir.push(element)
try {
if (!fs.existsSync(path.resolve(outDir.join('/')))) {
fs.mkdirSync(path.resolve(outDir.join('/')))
console.log('mkdir succeeded!!')
}
} catch (err) {
console.error(err)
}
})
The answer is from #thefourtheye, Use fs-extra module's mkdirs

Resources