Как я могу рекурсивно сделать каталог в последних каталогах с помощью командной строки?

Скажем, то, что у меня есть следующая структура каталогов, где название каталогов не имеет значения:

currentDir/
   Dir1
      Dir1
         Dir1 *
      Dir2 *
      Dir3 *
   Dir2
      Dir1 *
      Dir2 
         Dir1*
   Dir3*

Есть ли способ, которым я могу создать каталог под названием "Структура" только в каталогах в конце древовидного ответвления (в примере, они отмечены с *). Я хотел бы сделать его так, чтобы только те каталоги получили a Texture каталог, но не любые другие.

Все каталоги могут или не могут иметь файлов, но каталоги конца не будут иметь никаких других каталогов в них.

5
задан 26 September 2017 в 13:39

4 ответа

Сначала включите рекурсивный 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 печатает их как ? - каждая строка должна запуститься с буквы, указывающей на тип файла, таким образом, вероятно, никакие котята не умрут.

6
ответ дан 23 November 2019 в 08:42

Это должно работать:

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
3
ответ дан 23 November 2019 в 08:42

Вот болезненное 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
5
ответ дан 23 November 2019 в 08:42

Python делает это легким.

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.

1
ответ дан 23 November 2019 в 08:42

Другие вопросы по тегам:

Похожие вопросы: