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

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

У меня та же проблема, что была задана в вопросе Переименуйте музыкальные файлы с отсутствующими расширениями и я нашел скрипт, предоставленный @Gilles, очень познавательным, но, к сожалению, он не сработал так, как я ожидал. Я искал скрипт, который добавлял бы расширение файла ко всем музыкальным файлам без расширения во всех подкаталогах, на всех уровнях, ниже "/path/to/music/directory/". Предложенный параметр командной строки

/path/to/music/directory/{**/,}*

заставляет скрипт проходить по всем файлам в подкаталогах на один уровень ниже "/path/to/music/directory/", но не на уровнях ниже этого. Какой параметр командной строки мне следует использовать для прохождения по всем файлам на всех уровнях ниже "directory/"?

Также был бы признателен за ссылку на документацию по

{**/,}* 

часть.

BTW, для тех, кто интересуется оригинальным ответом. Я обнаружил, что скрипт работает лучше после того, как я изменил строку

file -i "$@" |

к

file --mime-type "$@" | 

(Если бы у меня был уровень привилегий, я бы указал это в качестве комментария в оригинальном ответе)

решение1

Я думаю, вам нужно только активировать globstarопцию bash, потому что по умолчанию она не активна вУбунту, как поясняется ниже.

Выражение /path/to/music/directory/{**/,}*содержит две конструкции расширения: расширение фигурных скобок и следующее за ним расширение имени пути.

Расширение скобок

Расширение скобок лучше всего объяснить на примере:

$ printf '%s\n' before-{a,bb,1,22}-after
before-a-after
before-bb-after
before-1-after
before-22-after

(Здесь и далее я использовал команду, printf '%s\n' item1 item2 etc..похожую на ту, echoно печатающую каждый элемент на новой строке)

Вы видите, что каждый элемент, разделенный запятой в фигурных скобках, приводит к созданию развернутого элемента.

Исходный пример, содержащий в фигурных скобках элементы **/и пустой элемент, расширяется до

$ printf '%s\n' /path/to/music/directory/{**/,}*
/path/to/music/directory/**/*
/path/to/music/directory/*

Глобстар

Теперь обратимся к bash glob **, который упоминается дважды встраница руководства bash, как по отношению к опции оболочки globstar, так и по отношению к ней, и значение следующее:

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

Этот вариант оболочки неактивныйпо умолчанию в Ubuntu:

$ shopt globstar
globstar        off

Вы можете активировать его с помощью

shopt -s globstar

(используйте shopt -u globstarдля его деактивации).

Если у нас есть следующая структура каталогов:

$ find first/ | sort
first/
first/aaa
first/second
first/second/bbb01
first/second/bbb02
first/second/third
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

у нас могут быть следующие расширения:

$ printf '%s\n' first/**/a*
first/aaa

$ printf '%s\n' first/**/b*
first/second/bbb01
first/second/bbb02

$ printf '%s\n' first/**/c*
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

Итак, вы видите, что **он может расширяться не только до элемента имени пути.

решение2

Я бы сделал что-то вроде этого

#! /bin/bash

[[ -d "$1" ]] || { echo "$1 not a directory, exiting..."; exit 1; }

find "$1" -type f | while read F; do
  # do what you want with the "$F"
done

exit 0

а затем вызвать скрипт через./my_script <directory>

Связанный контент