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