2012-02-26 2 views
82

Я знаю, вы можете сделать mkdir, чтобы создать каталог и touch, чтобы создать файл, но нет ли способа обойти обе операции за один раз?Unix - создать путь к папкам и файлу

т.е., если я хочу сделать ниже, если папка 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 

Кто-нибудь придумать функцию, как обходной путь для этого?

+0

Нашел: http://stackoverflow.com/questions/1529946/linux-copy-and-create-destination-dir-if-it-does-not -exist –

+0

Если необходимо, чтобы создание файла и его каталога было атомарным, вам нужно написать файловую систему, которая предлагает эту операцию. Это невозможно в стандартных файловых системах Linux. –

+0

@toop Я понимаю, что этот вопрос сейчас полтора года, но недавно были объединены несколько ответов. Если вам нужно очень часто, вы можете найти [мой ответ] (http://stackoverflow.com/a/19288855/119527) полезным. (Я бы стал более полезным, чем принятый ответ, но я не прошу представить здесь :-)) –

ответ

94

Использование && объединить две команды в одной строке оболочки:

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

Примечание: Ранее я рекомендовал использование ; отделить две команды, но, как указано @trysis, вероятно, лучше использовать && в большинстве ситуаций, потому что в случае, если COMMAND1 не работает COMMAND2 также не будет выполнен. (В противном случае это может привести к проблемам вы не могли бы ожидали.)

+9

Наверное, лучше использовать '&&', как и при ';', если первая команда завершится неудачно, вторая команда все равно будет выполняться (и также сбой, как и этот каталог пока не существует). С '&&', если первая команда не работает, вторая команда не запускается. – trysis

+4

Краткое описание примера кода может быть следующим: 'mkdir -p/my/other/path/here && touch $ _/cpredthing.txt'. '$ _' расширяет по существу« последний аргумент в последней выполненной команде ». – Sgnl

+3

@Sgnl yours - возможно правильный ответ. Это не просто чище, он менее подвержен ошибкам. – meetalexjohnson

10

вы можете сделать это в два этапа:

mkdir -p /my/other/path/here/ 
touch /my/other/path/here/cpedthing.txt 
12
#!/bin/sh 
for f in "[email protected]"; do mkdir -p "$(dirname "$f")"; done 
touch "[email protected]" 
+0

Анонимный пользователь предложил (через edit) использовать 'dirname -z" $ @ "| xargs -0 mkdir -p' вместо этого, ради производительности. (Прекратите скрываться и присоединитесь, ради Пита! ;-) – jpaugh

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

нет необходимости для if then заявлений ... вы можете сделать это на одной линии usign ;

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 предотвращает возвраты ошибок, если каталог уже существует (это то, что я пришел ее e ищет :))

51

Сначала необходимо создать все родительские каталоги.

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

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

Если вы хотите, чтобы получить творческий, вы можете make a function:

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

    for f in "[email protected]"; do 
     mkdir -p -- "$(dirname -- "$f")" 
     touch -- "$f" 
    done 
} 

И затем использовать его как любой другой команды:

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

Должен ли он сделать это двумя шагами, используя две команды? –

+0

Изменил его, чтобы использовать '&&' - Как это? –

+0

Является ли bash поддержкой возврата в функциях? –

1

В специальной (но не необычный) случай, когда вы пытаетесь воссоздать одну и ту же иерархию каталогов, может оказаться полезным cp --parents.

Например, если /my/long содержит исходные файлы, и my/other уже существует, вы можете сделать это:

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

, если вы хотите просто с только 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 
+2

Если вы хотите просто избавиться от работы за последние несколько часов, безвозмездно бросьте вокруг некоторых команд 'rm -rf'. - † То есть, _hours_, предполагая, что вы придерживаетесь разумной политики управления версиями/резервного копирования ... в противном случае это может быть месяцы. – leftaroundabout

0

, как я видел, и тест на форуме unix, это решает проблему

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

Сделайте это остроумие ч/USR/бен/установка:

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

Я удивлен, что этот инструмент драгоценных камней в значительной степени игнорируется - человек устанавливает - покажет, что установка - лучшее решение. –

2

Это то, что я хотел бы сделать:

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 
Смежные вопросы