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 це неможливо.
Пітер Г.

@toop Я розумію, що це питання зараз вже півтора року, але нещодавно в це було об'єднано кілька відповідей. Якщо вам потрібен такий предмет дуже часто, ви можете вважати мою відповідь корисною. (Я б заперечував корисніше, ніж прийняту відповідь, але я тут не прошу реп :-))
Джонатан Райнхарт


@tdammers Q: "Як зробити X?" A: "Ось як це зробити Y"
Генрі Генрінсон

Відповіді:


139

Використовуйте &&для об'єднання двох команд в одному рядку оболонки:

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

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


16
Ймовірно, краще використовувати &&, як і у ;випадку, якщо перша команда не вдасться, друга команда все одно запуститься (і теж не вдасться, оскільки цього каталогу ще не існує). З, &&якщо перша команда не працює, друга команда не запускається.
trysis

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

Змінив його на використання &&- як це?
Джонатан Райнхарт

1
@ BЈович Так . (Я намагаюся перевірити речі, перш ніж їх розміщувати.)
Джонатан Райнхарт

2
@JonathonReinhart Ви впевнені, що ви протестували його? Я спробував, supertouch "/tmp/abc/def ghi/jkl mno.txt"і це не вдалося. Всі команди dirname, mkdirі touchдали erros.
devnull

2
@devnull Мабуть, недостатньо добре. Чорт ваших просторів :-) Виправлено.
Джонатан Райнхарт

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
Я здивований, що цей дорогоцінний інструмент значною мірою ігнорується - людина встановить - покаже, що встановлення є кращим рішенням.
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



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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.