nu_command/filesystem/
umkdir.rs

1#[allow(deprecated)]
2use nu_engine::{command_prelude::*, current_dir};
3use nu_protocol::NuGlob;
4use uu_mkdir::mkdir;
5#[cfg(not(windows))]
6use uucore::mode;
7
8#[derive(Clone)]
9pub struct UMkdir;
10
11const IS_RECURSIVE: bool = true;
12const DEFAULT_MODE: u32 = 0o777;
13
14#[cfg(not(windows))]
15fn get_mode() -> u32 {
16    !mode::get_umask() & DEFAULT_MODE
17}
18
19#[cfg(windows)]
20fn get_mode() -> u32 {
21    DEFAULT_MODE
22}
23
24impl Command for UMkdir {
25    fn name(&self) -> &str {
26        "mkdir"
27    }
28
29    fn description(&self) -> &str {
30        "Create directories, with intermediary directories if required using uutils/coreutils mkdir."
31    }
32
33    fn search_terms(&self) -> Vec<&str> {
34        vec!["directory", "folder", "create", "make_dirs", "coreutils"]
35    }
36
37    fn signature(&self) -> Signature {
38        Signature::build("mkdir")
39            .input_output_types(vec![(Type::Nothing, Type::Nothing)])
40            .rest(
41                "rest",
42                SyntaxShape::OneOf(vec![SyntaxShape::GlobPattern, SyntaxShape::Directory]),
43                "The name(s) of the path(s) to create.",
44            )
45            .switch(
46                "verbose",
47                "print a message for each created directory.",
48                Some('v'),
49            )
50            .category(Category::FileSystem)
51    }
52
53    fn run(
54        &self,
55        engine_state: &EngineState,
56        stack: &mut Stack,
57        call: &Call,
58        _input: PipelineData,
59    ) -> Result<PipelineData, ShellError> {
60        #[allow(deprecated)]
61        let cwd = current_dir(engine_state, stack)?;
62        let mut directories = call
63            .rest::<Spanned<NuGlob>>(engine_state, stack, 0)?
64            .into_iter()
65            .map(|dir| nu_path::expand_path_with(dir.item.as_ref(), &cwd, dir.item.is_expand()))
66            .peekable();
67
68        let is_verbose = call.has_flag(engine_state, stack, "verbose")?;
69
70        if directories.peek().is_none() {
71            return Err(ShellError::MissingParameter {
72                param_name: "requires directory paths".to_string(),
73                span: call.head,
74            });
75        }
76
77        for dir in directories {
78            if let Err(error) = mkdir(&dir, IS_RECURSIVE, get_mode(), is_verbose) {
79                return Err(ShellError::GenericError {
80                    error: format!("{}", error),
81                    msg: format!("{}", error),
82                    span: None,
83                    help: None,
84                    inner: vec![],
85                });
86            }
87        }
88
89        Ok(PipelineData::empty())
90    }
91
92    fn examples(&self) -> Vec<Example> {
93        vec![
94            Example {
95                description: "Make a directory named foo",
96                example: "mkdir foo",
97                result: None,
98            },
99            Example {
100                description: "Make multiple directories and show the paths created",
101                example: "mkdir -v foo/bar foo2",
102                result: None,
103            },
104        ]
105    }
106}