Unix - create path of folders and file

153,997

Solution 1

Use && to combine two commands in one shell line:

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

Note: Previously I recommended usage of ; to separate the two commands but as pointed out by @trysis it's probably better to use && in most situations because in case COMMAND1 fails COMMAND2 won't be executed either. (Otherwise this might lead to issues you might not have been expecting.)

Solution 2

You need to make all of the parent directories first.

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

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

If you want to get creative, you can make a function:

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

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

And then use it like any other command:

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

Solution 3

Do it with /usr/bin/install:

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

when you don't have a source file:

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

Solution 4

This is what I would do:

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

Here, the $_ is a variable that represents the last argument to the previous command that we executed in line.

As always if you want to see what the output might be, you can test it by using the echo command, like so:

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

Which outputs as:

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

As a bonus, you could write multiple files at once using brace expansion, for example:

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

Again, totally testable with 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

Solution 5

#!/bin/sh
for f in "$@"; do mkdir -p "$(dirname "$f")"; done
touch "$@"
Share:
153,997
toop
Author by

toop

Updated on August 20, 2020

Comments

  • toop
    toop over 3 years

    I know you can do mkdir to create a directory and touch to create a file, but is there no way to do both operations in one go?

    i.e. if I want to do the below when the folder other does not exist:

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

    Error:

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

    Has anyone come up with a function as a workaround for this?

  • Seng Cheong
    Seng Cheong over 10 years
    Changed it to use && - How's that?
  • BЈовић
    BЈовић over 10 years
    Is bash supporting return in functions?
  • Seng Cheong
    Seng Cheong over 10 years
    @BЈовић Yes. (I do try to test things before I post them.)
  • devnull
    devnull over 10 years
    @JonathonReinhart Are you sure that you tested it? I tried supertouch "/tmp/abc/def ghi/jkl mno.txt" and it failed. All the commands dirname, mkdir, and touch gave erros.
  • Seng Cheong
    Seng Cheong over 10 years
    @devnull Apparently not well enough. Damn your spaces :-) Fixed.
  • devnull
    devnull over 10 years
    @JonathonReinhart Good to see that you've quoted the arguments.
  • trysis
    trysis almost 9 years
    Probably better to use &&, as with ;, if the first command fails, the second command will still run (and fail, too, as that directory does not exist yet). With && if the first command fails, the second command does not run.
  • Jeremy Iglehart
    Jeremy Iglehart about 8 years
    @JonathonReinhart I like the script very much, but suggest the name "mktouch" - added to my .profile - Thanks!
  • Seng Cheong
    Seng Cheong about 8 years
    @JeremyIglehart I like it. mktouch it is.
  • Sgnl
    Sgnl about 8 years
    A short cut for the code example can be: mkdir -p /my/other/path/here && touch $_/cpredthing.txt. The $_ expands to essentially the "last argument in the last command executed".
  • leftaroundabout
    leftaroundabout about 8 years
    If you want to simply get rid of the last few hours'† work, gratitiously throw around some rm -rf commands. — †That is, hours, assuming you adhere to a sensible version control / backup policy... otherwise, it might well be months.
  • SC-SL
    SC-SL over 7 years
    I am surprised this gem tool is largely ignored - man install - will show that install is a better solution.
  • Choylton B. Higginbottom
    Choylton B. Higginbottom over 6 years
    @Sgnl yours is arguably the correct answer. It is not just cleaner, it is less error-prone.
  • jpaugh
    jpaugh over 6 years
    An anonymous user suggested (via edit) to use dirname -z "$@" | xargs -0 mkdir -p instead, for performance's sake. (Stop lurking, and join, for Pete's sake! ;-)
  • wisbucky
    wisbucky almost 6 years
    You can also use -D /dev/null, which is easier for me to remember.
  • Mausy5043
    Mausy5043 over 5 years
    rm -rf should never be suggested without proper explanation and warnings.
  • Ben174
    Ben174 about 5 years
    I really wish touch took a -p parameter like mkdir does.