Unix - create path of folders and file

LinuxBashShellUnixScripting

Linux Problem Overview


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?

Linux Solutions


Solution 1 - Linux

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 - Linux

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 - Linux

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 - Linux

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 - Linux

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

Solution 6 - Linux

you can do it in two steps:

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

Solution 7 - Linux

if [ ! -d /my/other ]
then
   mkdir /my/other/path/here
   cp /my/long/path/here/thing.txt /my/other/path/here/cpedthing.txt
fi

Solution 8 - Linux

as I saw and test in a unix forum this solves the problem

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

Solution 9 - Linux

no need for if then statements... you can do it on a single line usign ;

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

-- or on two lines --

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

-- the -p prevents error returns if the directory already exists (which is what I came here looking for :))

Solution 10 - Linux

In the special (but not uncommon) case where you are trying to recreate the same directory hierarchy, cp --parents can be useful.

For example if /my/long contains the source files, and my/other already exists, you can do this:

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

Solution 11 - Linux

if you want simple with only 1 param snippet :

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontoopView Question on Stackoverflow
Solution 1 - LinuxevotopidView Answer on Stackoverflow
Solution 2 - LinuxJonathon ReinhartView Answer on Stackoverflow
Solution 3 - LinuxIvan DivesView Answer on Stackoverflow
Solution 4 - LinuxSgnlView Answer on Stackoverflow
Solution 5 - LinuxJavierView Answer on Stackoverflow
Solution 6 - LinuxJörg BeyerView Answer on Stackoverflow
Solution 7 - LinuxBarun ParichhaView Answer on Stackoverflow
Solution 8 - LinuxFabian RiosView Answer on Stackoverflow
Solution 9 - Linuxtediffer3rdView Answer on Stackoverflow
Solution 10 - LinuxTodd OwenView Answer on Stackoverflow
Solution 11 - LinuxstrangerView Answer on Stackoverflow