Скажем, то, что у меня есть следующая структура каталогов, где название каталогов не имеет значения:
currentDir/
Dir1
Dir1
Dir1 *
Dir2 *
Dir3 *
Dir2
Dir1 *
Dir2
Dir1*
Dir3*
Есть ли способ, которым я могу создать каталог под названием "Структура" только в каталогах в конце древовидного ответвления (в примере, они отмечены с *
). Я хотел бы сделать его так, чтобы только те каталоги получили a Texture
каталог, но не любые другие.
Все каталоги могут или не могут иметь файлов, но каталоги конца не будут иметь никаких других каталогов в них.
Сначала включите рекурсивный globbing
shopt -s globstar
Теперь мы можем посмотреть во всех каталогах с **
. Для сбрасывания можно использовать shopt -u globstar
(это прочь по умолчанию, таким образом, это будет выключено при открытии новой оболочки).
Во всем из ниже, удалить echo
после тестирования для фактического создания каталогов.
Если каталоги конца дерева пусты, Вы могли бы протестировать на пустоту и сделать каталог, только если это обнаруживается... что-то как
for d in **/; do [[ -z "$(ls -Aq "$d")" ]] && echo mkdir "$d"Texture; done
т.е. если вывод ls -A (hidden files except current and parent dir) -q (printing ? for non-printing characters)
пусто, сделайте каталог.
Но так как каталоги содержат файлы, мы должны протестировать это нет никаких каталогов
for d in **/; do [[ -z "$(find "$d" -maxdepth 1 -mindepth 1 -type d)" ]] && echo mkdir "$d"Texture; done
mindepth -1
должен остановить находимый текущий каталог... find
видит скрытые файлы, таким образом, мы знаем, что они включены. Так как любой символ должен пройти тест (мы только хотим проверить, что вывод пуст), это должно быть довольно безопасно...
Более краткий путь (жаль Greg) (но на самом деле все эти методы делают что-то столь же сомнительное - нам может примерно сойти с рук использование имен файлов как текст, так как мы на самом деле не пытаемся сделать что-либо с теми файлами самими здесь):
for d in **/; do (ls -Alq "$d" | grep -q '^d') || echo mkdir "$d"Textures; done
здесь мы добавляем -l
флаг для долгого вывода, который печатает каждый файл в форме
drwxrwxr-x 5 zanna zanna 4096 Sep 27 22:00 Dir1
мы затем проглатываем канал тот материал в grep
видеть, запускается ли какая-либо из строк с d
(значение существует каталог). Мы не хотим grep
распечатать любой тот бессмысленный ненадежный текст, таким образом, мы просто проверяем его статус выхода с -q
видеть, нашло ли это что-нибудь. Если это не сделало, мы делаем каталог (использующий ||
или оператор, значение, делает следующую команду, если последний перестал работать). Это должно работать, на самом деле, даже если Ваши имена файлов содержат ужасные символы, такие как новые строки с тех пор ls
печатает их как ?
- каждая строка должна запуститься с буквы, указывающей на тип файла, таким образом, вероятно, никакие котята не умрут.
Это должно работать:
shopt -s globstar; for i in **/; do sub=$(find "$i" -type d | wc -l); if [[ "$sub" -eq 1 ]]; then mkdir "$i"/Texture; fi;done
Результат:
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ │ └── Texture
│ ├── Dir2
│ │ └── Texture
│ └── Dir3
│ └── Texture
├── Dir2
│ ├── Dir1
│ │ └── Texture
│ └── Dir2
│ └── Dir1
│ └── Texture
└── Dir3
└── Texture
Вот болезненное find -exec
звонить
Прежде:
$ tree currentDir
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ ├── Dir2
│ └── Dir3
├── Dir2
│ ├── Dir1
│ └── Dir2
│ └── Dir1
└── Dir3
Создайте каталоги Texture
$ find currentDir -depth -type d -exec bash -c 'cd "$1"; shopt -s globstar nullglob; texture=(**/Texture); [[ ${#texture[@]} -eq 0 ]] && mkdir Texture' _ '{}' \;
Это полагается:
-depth
опция включить навигацию в глубинуglobstar
опция оболочки включить рекурсивное сопоставление с образцом файла_
аргумент: это входит в var удара $0
так, чтобы текущий путь находки мог быть var удара $1
После
$ tree currentDir
currentDir
├── Dir1
│ ├── Dir1
│ │ └── Dir1
│ │ └── Texture
│ ├── Dir2
│ │ └── Texture
│ └── Dir3
│ └── Texture
├── Dir2
│ ├── Dir1
│ │ └── Texture
│ └── Dir2
│ └── Dir1
│ └── Texture
└── Dir3
└── Texture
python3 -c 'import os
for d in [root for root, dirs, files in os.walk(".") if not any(dirs)]:
os.mkdir(d + "/Texture")'
Можно выполнить ту команду от оболочки. Это передает сценарий с тремя линиями интерпретатору Python 3, который выполняет его. Сценарий создает список всех каталогов под .
(тот, в котором Вы находитесь), затем создает a Texture
подкаталог в каждом, который уже не имел никаких подкаталогов.
Это более просто записать и легче понять, чем большинство других методов, потому что Python имеет os.walk
функция, которая перечисляет каталоги способом, который помогает видеть, которые имеют подкаталоги (и в более общем плане потому что Python является языком, который многие пользователи находят чистыми и интуитивными).
Если бы Вы хотите просто показать, какие новые каталоги были бы созданы вместо того, чтобы на самом деле создать их, замену os.mkdir
с print
. Вот это, в случае, если Вы хотите скопировать и вставить:
python3 -c 'import os
for d in [root for root, dirs, files in os.walk(".") if not any(dirs)]:
print(d + "/Texture")'
Существуют способы записать любую из этих команд с тремя линиями на одной строке, но нет никакой потребности. Можно ввести команду, которую Вы хотите использовать на интерактивном приглашении оболочки путем ввода или вставки его в, или можно использовать его в сценарии оболочки. При интерактивном вводе оболочка распечатает >
(если Вы не установили $PS2
к чему-то другому) в начале вторых и третьих строк. Это не проблема.
Предшествующее предполагает использование оболочки стиля Границы как bash
, dash
/sh
, ksh
, zsh
, posh
, и т.д. (ОнитриответыИспользование shopt -s globstar
. Та команда является определенной для Bash, хотя некоторые другие оболочки имеют подобную функцию. Таким образом, если они работают на Вас, это должно также.) При использовании Ubuntu и Вы не знаете то, что окружает, Вы вводите команды в, это bash
. Если Вы используете csh
или tcsh
, необходимо будет поместить a \
в концах первых двух строк, которые избегут Unmatched '.
ошибка, и Вы будете видеть ?
вместо >
.
Для тестирования этого метода на существующей иерархии каталогов, не создавая каталоги просто используйте вторую команду, как описано выше. Но если Вам нравится, можно сделать новую иерархию каталогов где-нибудь просто для тестирования. mkdir -p dir/{a/{b/c,d,e},f/{g,h/i},j}
создает дерево каталогов с той же топологией как та в Вашем примере; find dir -type d -exec touch {}/x \;
заполняет его с некоторыми файлами, таким образом, можно проверить, что присутствие некаталогов не является проблемой; cd dir
входит в него; и затем можно протестировать команды, показанные выше, а также любой другой метод, можно интересоваться, такие как представленные в других ответах; затем выполненный tree
.