nu_command/filesystem/
mktemp.rs

1#[allow(deprecated)]
2use nu_engine::{command_prelude::*, env::current_dir};
3use std::path::PathBuf;
4
5#[derive(Clone)]
6pub struct Mktemp;
7
8impl Command for Mktemp {
9    fn name(&self) -> &str {
10        "mktemp"
11    }
12
13    fn description(&self) -> &str {
14        "Create temporary files or directories using uutils/coreutils mktemp."
15    }
16
17    fn search_terms(&self) -> Vec<&str> {
18        vec![
19            "create",
20            "directory",
21            "file",
22            "folder",
23            "temporary",
24            "coreutils",
25        ]
26    }
27
28    fn signature(&self) -> Signature {
29        Signature::build("mktemp")
30            .input_output_types(vec![(Type::Nothing, Type::String)])
31            .optional(
32                "template",
33                SyntaxShape::String,
34                "Optional pattern from which the name of the file or directory is derived. Must contain at least three 'X's in last component.",
35            )
36            .named("suffix", SyntaxShape::String, "Append suffix to template; must not contain a slash.", None)
37            .named("tmpdir-path", SyntaxShape::Filepath, "Interpret TEMPLATE relative to tmpdir-path. If tmpdir-path is not set use $TMPDIR", Some('p'))
38            .switch("tmpdir", "Interpret TEMPLATE relative to the system temporary directory.", Some('t'))
39            .switch("directory", "Create a directory instead of a file.", Some('d'))
40            .category(Category::FileSystem)
41    }
42
43    fn examples(&self) -> Vec<Example> {
44        vec![
45            Example {
46                description: "Make a temporary file with the given suffix in the current working directory.",
47                example: "mktemp --suffix .txt",
48                result: Some(Value::test_string("<WORKING_DIR>/tmp.lekjbhelyx.txt")),
49            },
50            Example {
51                description: "Make a temporary file named testfile.XXX with the 'X's as random characters in the current working directory.",
52                example: "mktemp testfile.XXX",
53                result: Some(Value::test_string("<WORKING_DIR>/testfile.4kh")),
54            },
55            Example {
56                description: "Make a temporary file with a template in the system temp directory.",
57                example: "mktemp -t testfile.XXX",
58                result: Some(Value::test_string("/tmp/testfile.4kh")),
59            },
60            Example {
61                description: "Make a temporary directory with randomly generated name in the temporary directory.",
62                example: "mktemp -d",
63                result: Some(Value::test_string("/tmp/tmp.NMw9fJr8K0")),
64            },
65        ]
66    }
67
68    fn run(
69        &self,
70        engine_state: &EngineState,
71        stack: &mut Stack,
72        call: &Call,
73        _input: PipelineData,
74    ) -> Result<PipelineData, ShellError> {
75        let span = call.head;
76        let template = call
77            .rest(engine_state, stack, 0)?
78            .first()
79            .cloned()
80            .map(|i: Spanned<String>| i.item)
81            .unwrap_or("tmp.XXXXXXXXXX".to_string()); // same as default in coreutils
82        let directory = call.has_flag(engine_state, stack, "directory")?;
83        let suffix = call.get_flag(engine_state, stack, "suffix")?;
84        let tmpdir = call.has_flag(engine_state, stack, "tmpdir")?;
85        let tmpdir_path = call
86            .get_flag(engine_state, stack, "tmpdir-path")?
87            .map(|i: Spanned<PathBuf>| i.item);
88
89        let tmpdir = if tmpdir_path.is_some() {
90            tmpdir_path
91        } else if directory || tmpdir {
92            Some(std::env::temp_dir())
93        } else {
94            #[allow(deprecated)]
95            Some(current_dir(engine_state, stack)?)
96        };
97
98        let options = uu_mktemp::Options {
99            directory,
100            dry_run: false,
101            quiet: false,
102            suffix,
103            template,
104            tmpdir,
105            treat_as_template: true,
106        };
107
108        let res = match uu_mktemp::mktemp(&options) {
109            Ok(res) => res
110                .into_os_string()
111                .into_string()
112                .map_err(|_| ShellError::NonUtf8 { span })?,
113            Err(e) => {
114                return Err(ShellError::GenericError {
115                    error: format!("{}", e),
116                    msg: format!("{}", e),
117                    span: None,
118                    help: None,
119                    inner: vec![],
120                });
121            }
122        };
123        Ok(PipelineData::Value(Value::string(res, span), None))
124    }
125}