mkdir -p для файлів


24

mkdir -pстворить каталог; він також зробить батьківські каталоги за потребою.

Чи існує аналогічна команда для файлів, яка створить файл та батьківські каталоги за потребою?


Не те, що я знаю .. але ви могли просто зробити mkdir -p / path / to / make && touch / path / to / file ... Який би створив порожній файл у тій новій структурі каталогу, яку ви створили всі за потребою.

1
@Kansha поєднати це з dirnameі basenameнам знадобиться лише один аргумент; прибуток! :)

Так, хороший дзвінок.

Відповіді:


29

Установка зробить це, якщо вказати вихідний файл /dev/null. -DАргумент каже , щоб створити всі батьківські каталоги:

anthony@Zia:~$ install -D /dev/null /tmp/a/b/c
anthony@Zia:~$ ls -l /tmp/a/b/c 
-rwxr-xr-x 1 anthony anthony 0 Jan 30 10:31 /tmp/a/b/c

Не впевнений, що це помилка чи ні - її поведінка з файлами пристрою не згадується на сторінці сторінки. Ви також можете просто дати йому порожній файл (щойно створений mktemp, наприклад, як джерело).


7

Ні, це не наскільки я знаю. Але ви завжди можете використовувати mkdir -pі touchодин за одним:

f="/a/b/c.txt"
mkdir -p -- "${f%/*}" && touch -- "$f"

3

Я часто стикався з подібною ситуацією, тому просто записав функцію у свій .bashrcфайл. Це виглядає приблизно так

function create() {
    arg=$1
    num_of_dirs=$(grep -o "/" <<< $arg | wc -l)
    make_dirs=$(echo $arg | cut -d / -f1-$num_of_dirs)
    mkdir -p $make_dirs && touch $arg
}

Отже, коли я хочу створити файл всередині контуру неіснуючих каталогів, я скажу

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'

1
Мій чоловік! - дякую, я назвав це touchp, якmkdir -p
екологічний

0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"

3
testНе потрібно; mkdir -pнічого не робить, якщо режисер вже існує. Навіть не повертає помилку.
дероберт

1
І звичайно, це лише створює каталог.
CVn

0

Я збирався запропонувати, оскільки він зберігає його в одному рядку, хоча встановлення змінної окремо дозволяє змінити її і перезапустити команду з історії досить легко.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"

0

Можна «підробити».

По-перше, деякі необхідні теорії:

Роб Гріффітс опублікував статтю в 2007 році під назвою Легко створювати багато нових папок на Macworld.com, де він обговорював використання xargsкоманди для читання у списку файлів для створення каталогів за допомогоюmkdir .

xargsздатний посилати placeholder( {}) на -Iпрапор, який містить значення для кожного переданого аргументу xargs. Ось різниця між цим прапором і без:

$ foo.txt bar.txt | xargs echo
$ => foo.txt bar.txt
$ foo.txt bar.txt | xargs -I {} echo {}
$ => foo.txt
$ => bar.txt

xargsтакож здатний виконувати довільні команди оболонки з sh -cпрапором:

foo.txt bar.txt | xargs sh -c 'echo arbitrary command!'

Поєднання понять:

Ми можемо об'єднати ці поняття з mkdir -pзамість mkdirі поняття в @ldx «s відповіді зробити це:

$ cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"'

Ця команда в основному відображає кожне ім'я файлу в розділеному рядком списку файлів, відсікає частину файлу, створює каталоги з, mkdir -pа потімtouch видає ім'я файлу у відповідній директорії.

Ось розбивка того, що відбувається у наведеній вище команді:

Скажімо, наприклад, моє files.txtвиглядає так:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt виробляє deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt трубопровід до xargs
  • тому що ми використовували -I {}, xargsпереведемо кожен аргумент у свою власну команду, тож тепер у нас є:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • Потім ми запускаємо команду оболонки, яка використовує &&комбінатор для групування команд 3, які виконуються послідовно - перша команда зберігає файл у змінній оточення (що повторно використовується при наступному пропуску файлу), використовуючи заповнений нами місце раніше, тому ми тепер мають:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • тепер у нас є змінна, до якої ми можемо перейти mkdir -p, але нам потрібно вирізати ім’я файлу. Досить просто за допомогою '${f%/*}':
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • а потім ми просто перенаправляємо fзмінну в повному обсязі, коли touch:
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt

2
У вас є все це пояснення того, що є по суті cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"', що має UUOC, тоді ви перебуваєте в підрозділі xargs, який знаходиться в оболонці, коли while readцикл має більше сенсу
Стівен Пенні,

1
Я визнаю, що я не найбільше чіпляється про * nix команди - я навіть не знаю, що таке UUOC, - але я не розумію, як це жахлива відповідь. Він досліджений, перевірений і є робочим рішенням вашого оригінального питання. Це конструктивно (на відміну від вашого досить грубого коментаря). Будь ласка, якщо ви відчуваєте, що я тут зробив щось безвідповідальне, чого мені не довелося, тоді детальніше поясніть - поясніть чому . Мене мало хвилює самовпевнена дискусія, яка не має суті.
бритвою

1
Мій останній коментар це чудово пояснює. Всю вашу відповідь можна було б краще записати як while read f; do mkdir -p "$(dirname "$f")"; touch "$f"; done < files.txt. Про те, що ви не можете зробити 10-секундний Інтернет-пошук для UUOC, також говорить
Стівен Пенні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.