Unix-创建文件夹和文件的路径


125

我知道您可以mkdir创建目录和touch文件,但是无法一次性完成这两种操作吗?

即如果我想在文件夹other不存在时执行以下操作:

cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

错误:

cp: cannot create regular file `/my/other/path/here/cpedthing.txt': No such file or directory

有没有人想出一个功能来解决这个问题?



如果必须以原子方式创建文件及其目录,则必须编写一个提供此操作的文件系统。标准Linux文件系统是不可能的。
彼得·G。

@toop我知道这个问题已经有一年半了,但是最近有几个答案合并到了这个问题中。如果您经常需要这种类型的东西,您可能会发现我的回答很有用。(我认为比接受的答案有用,但我在这里不求代表:
乔纳森·莱因哈特


@tdammers问:“我怎么做X?” 答:“这是Y的方法”
Henry Henrinson

Answers:


139

使用&&两个命令在一个外壳线面相结合:

COMMAND1 && COMMAND2
mkdir -p /my/other/path/here/ && touch /my/other/path/here/cpedthing.txt

注意:以前我建议使用;来分隔两个命令,但是正如@trysis所指出的,&&在大多数情况下使用它可能更好,因为万一COMMAND1失败COMMAND2也不会执行。(否则,这可能会导致您可能没有想到的问题。)


16
&&与一起使用可能更好;,如果第一个命令失败,则第二个命令仍将运行(并且也失败,因为该目录尚不存在)。随着&&如果第一个命令失败,第二个命令不会运行。
trysis 2015年

12
该代码示例的捷径可以是:mkdir -p /my/other/path/here && touch $_/cpredthing.txt。在$_基本上与扩张“在最后一个命令最后的参数执行”。
Sgnl

4
@Sgnl是您的正确答案。它不仅更清洁,而且不易出错。
Choylton B. Higginbottom

3
我真的希望像这样touch接受一个-p参数mkdir
Ben174

86

您需要先创建所有父目录。

FILE=./base/data/sounds/effects/camera_click.ogg

mkdir -p "$(dirname "$FILE")" && touch "$FILE"

如果您想发挥创意,可以创建一个函数

mktouch() {
    if [ $# -lt 1 ]; then
        echo "Missing argument";
        return 1;
    fi

    for f in "$@"; do
        mkdir -p -- "$(dirname -- "$f")"
        touch -- "$f"
    done
}

然后像其他命令一样使用它:

mktouch ./base/data/sounds/effects/camera_click.ogg ./some/other/file

更改为使用&&-怎么样?
Jonathon Reinhart

1
@BЈовић 是的。(在发布之前,我确实尝试过测试。)
Jonathon Reinhart

2
@JonathonReinhart确定要测试吗?我尝试了supertouch "/tmp/abc/def ghi/jkl mno.txt",但失败了。所有命令dirnamemkdirtouch给出了错误。
devnull

2
@devnull显然不够好。该死的空间:-)固定。
Jonathon Reinhart

1
@JeremyIglehart我喜欢。mktouch它是。
乔纳森·莱因哈特

24

使用/ usr / bin / install来执行此操作:

install -D /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

当您没有源文件时:

install -D <(echo 1) /my/other/path/here/cpedthing.txt

1
令我惊讶的是,这个gem工具在很大程度上被忽略了-man install-将显示install是一个更好的解决方案。
SC-SL

1
您也可以使用-D /dev/null,这对我来说更容易记住。
wisbucky

14

这就是我要做的:

mkdir -p /my/other/path/here && touch $_/cpredthing.txt

在这里 $_是一个变量,代表我们在线执行的上一个命令的最后一个参数。

与往常一样,如果您想查看输出结果,可以使用以下echo命令对其进行测试,如下所示:

echo mkdir -p /code/temp/other/path/here && echo touch $_/cpredthing.txt

输出为:

mkdir -p /code/temp/other/path/here
touch /code/temp/other/path/here/cpredthing.txt

另外,您可以使用大括号扩展一次写入多个文件,例如:

mkdir -p /code/temp/other/path/here &&
touch $_/{cpredthing.txt,anotherfile,somescript.sh}

再次,完全可以测试echo

mkdir -p /code/temp/other/path/here
touch /code/temp/other/path/here/cpredthing.txt /code/temp/other/path/here/anotherfile /code/temp/other/path/here/somescript.sh

13
#!/bin/sh
for f in "$@"; do mkdir -p "$(dirname "$f")"; done
touch "$@"

1
dirname -z "$@" | xargs -0 mkdir -p为了提高性能,一个匿名用户建议(通过编辑)改为使用。(停止潜伏,并加入,为了皮特的缘故!;-)
jpaugh

11

您可以分两个步骤进行操作:

mkdir -p /my/other/path/here/
touch /my/other/path/here/cpedthing.txt


2

正如我在Unix论坛中看到并测试的那样,这解决了问题

ptouch() {
    for p in "$@"; do
        _dir="$(dirname -- "$p")"
        [ -d "$_dir" ] || mkdir -p -- "$_dir"
    touch -- "$p"
    done
}

1

无需if then声明...您可以单行完成;

mkdir -p /my/other/path/here;cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

-或两行-

mkdir -p /my/other/path/here
cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt

- -p如果目录已经存在,则防止错误返回(这就是我在这里寻找的内容:))


1

在特殊(但不罕见)的情况下,您尝试重新创建相同的目录层次结构cp --parents可能会很有用。

例如,如果/my/long包含源文件并且my/other已经存在,则可以执行以下操作:

cd /my/long
cp --parents path/here/thing.txt /my/other

-4

如果您只想简单使用1个参数片段:

rm -rf /abs/path/to/file;  #prevent cases when old file was a folder
mkdir -p /abs/path/to/file; #make it fist as a dir
rm -rf /abs/path/to/file; #remove the leaf of the dir preserving parents 
touch /abs/path/to/file; #create the actual file

3
如果您只想摆脱最后几个小时的工作,请免费使用一些rm -rf命令。—†也就是说,假设您遵守明智的版本控制/备份策略,则是小时,否则,可能要几个月。
大约

1
rm -rf未经适当的解释和警告,切勿提出建议。
Mausy5043 '18 -10-23
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.