Как мне создать каталог во всех подкаталогах?


34

Предположим, у меня есть такая структура каталогов:

$ [~ / practice] ls
а / б / ц / д /

Теперь я хочу создать каталог tmp1во всех подкаталогах practiceи я делаю это:

$ [~ / practice] mkdir * / tmp1
mkdir: невозможно создать каталог `* / tmp1 ': такого файла или каталога нет

Затем я пытаюсь -pпереключиться и я в конечном итоге с каталогом с именем *подкаталогtmp1

$ [~ / practice] mkdir -p * / tmp1

$ [~ / practice] ls
* / a / b / c / d /

Я знаю, что использование -pпереключателя для создания нескольких несуществующих каталогов. Я просто подумал, что это может помочь.

Как создать сразу tmp1во всех подкаталогах?

Если это может быть сделано, как я его расширить для создания \tmp1, \tmp2, \tmp3в \a, \bи \cсразу?

Изменить: Я пропустил упоминание о том , что каталоги не должны быть простыми и в порядке, как a, b, и cт.д., и каталог будет создан не обязательно , как tmp1, tmp2.

$ [~ / practice] ls
собака / кошка / крыса /

В них хотелось бы иметь что-то вроде

$ [~ / practice] ls *
собака:
красно синий/

Кот:
красно синий/

крыса:
красно синий/

1
Учитывая ответ Кристофера , вы должны уточнить, должны ли "create \ tmp1, \ tmp2, \ tmp3 in \ a, \ b и \ c" иметь в общей сложности 3 или 9 подкаталогов.
manatwork

@ Manatwork: Это хороший момент. Следует создать 9 подкаталогов.
Анимеш

Это моя помощь для решения проблемы с пространством в имени каталога sudo find ./ -depth -type d -exec echo '"{} / RCS"' \;

Ответы:


44

С шариками :

for dir in */; do mkdir -- "$dir/tmp1"; done

НОТА

  • Я рассматриваю только dirs (включая символические ссылки на dirs) с небольшим хакерским использованием */ как glob
  • Если вы хотите создать несколько подкаталогов одновременно:

    for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done


Могу ли я сделать for i in */; do mkdir "$i/itemone" "$i/itemtwo"; doneдля нескольких, не по порядку имена каталогов?
Анимеш

Я проверил это, и это очень возможно. Спасибо.
Анимеш

Смотрите мое отредактированное сообщение
Gilles Quenot

1
Расширение скобок в строке в кавычках не выполняется.
manatwork

Да, спасибо, сообщение отредактировал Стефан Шазелас соответственно ...
Жиль Квено

10

[...] как мне расширить его для одновременного создания \ tmp1, \ tmp2, \ tmp3 в \ a, \ b и \ c?

 mkdir {a,b,c}/tmp{1,2,3}

10

С GNU или BSD * найти:

find -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/newdir \;

или используя расширение параметра:

dirs=(*/)
mkdir -- "${dirs[@]/%/newdir}"

* Включает OS X


2
Со стандартным синтаксисом поиска:find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \;
Стефан Шазелас

1
Также обратите внимание на различия между двумя решениями: первое включает в себя скрытые каталоги, второе добавит новый каталог в каталоги, связанные любой символической ссылкой в ​​текущем каталоге.
Стефан Шазелас

6

Не по теме, так как вы упоминаете bash, но для записи, с zsh, вы бы сделали:

dirs=(*(/))
mkdir -- $^dirs/tmp1

$^varвключает в себя фигурное расширение для расширения массива. Это напоминает оператор rcs ^и в rc(или его производную es), вы бы написали:

dirs=(*/)
mkdir -- $dirs^tmp1

Однако обратите внимание (и то же самое относится к решениям bash, приведенным здесь), что в решении rc dirsтакже будут содержаться символические ссылки на каталоги. В решении zsh измените *(/)на, *(-/)если хотите включить символические ссылки на каталоги.


+1 за ваше мнение о символических ссылках! Такое поведение может быть желательным, но жалоба mkdir на создание дублирующегося каталога может быть подавлена ​​с помощью -pфлага.
Кодзиро

4

Похоже, цикл по родительским каталогам:

for d in */; do mkdir "$d/red" "$d/blue"; done

Добавьте --после, mkdirесли у вас могут быть каталоги, название которых начинается с -.

В zsh вы можете сделать это с помощью команды e glob :

mkdir *(/e\''REPLY=($REPLY/{red,blue})'\')

но быстрее набрать это двумя командами:

d=(*(/)); mkdir $^d/{red,blue}

1
На сайте, который должен быть ссылкой, я бы скорее сказал « mkdir -- whateverи опускаю, -- если вы намерены расширить то, что может быть принято в качестве опции для mkdirкоманды». Там нет смысла опускать --здесь. Это может не быть проблемой в случае ОП, но это в общем случае. Я думаю, что мы обязаны преподавать правильный и безопасный синтаксис здесь.
Стефан Шазелас

@StephaneChazelas В контексте сценариев я всегда помещаю все необходимые --цитаты и большие жирные предупреждения, когда переводы строк не поддерживаются. В контексте командной строки я предпочитаю показывать быструю версию, которая сначала работает на практике, и пуленепробиваемую версию в качестве дополнения.
Жиль "ТАК ... перестать быть злым"


1

Вариация ответа sputnick, которая позволяет избежать файлов, не являющихся каталогами:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done

Я лечу только dirs, вот и вся магия ...
Жиль Квено

круто, понял;)
Златовласка

2
Не должно ли это быть if [ -d "$x" ];…?
Кодзиро

Да. У меня практически никогда нет пробелов в именах файлов, и я склонен забывать эти вещи ...
Златовласка

1

Это хороший вариант из старых Unix Masters (тестировался на FreeBSD 10.1), если вы хотите контролировать версию (с заблокированной проверкой RCS: ci -l с кратким комментарием как ir: для первоначального выпуска) ваших файлов конфигурации / etc / * на ~ / .his / etc

sudo rsync -av /etc/ ~/.his
sudo find -d ~/.his/etc -type d -exec echo '{}/RCS' \; | xargs sudo mkdir -p
sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir

Я не вижу, как этот ответ OP
Archemar

1

Должно быть \! Назовите "RCS", и это лучше всего работает при первой регистрации.

sudo найти ~ / .his / etc \! имя "RCS" -ls

sudo найти -d ~ / .his / etc \! имя "RCS" | xargs sudo ci -l -mir -t-ir

Этот последний также очень хорошо работает для cjeck в части фильтрации всего содержимого RCS по имени файла:

sudo find -d ~ / .his / etc -type f | grep -v RCS | xargs sudo ci -l -mir -t-ir


1

это большая помощь для меня. мне нужно было создать набор подкаталогов в нескольких папках и что-то вроде:

!/bin/sh

cd /dest/cont

for dir in */*/; do
    mkdir -p -- $dir/{FB,Video,Audio,proj};
done

работал отлично, за исключением случаев, когда встречается пробел. есть ли способ игнорировать пробелы в*/*/ части аргументов?

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.