Смущен тем, что "дерево" не находит файл

Использование утилиты Perl rename, если она доступна,

find. -type f -name '* (*)*' -exec rename 's/ \([^)]*\)//g' {} +

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

Если у вас нет rename, то...

Если вы хотите удалить все круглые скобки из всех имен обычных файлов в текущем каталоге или ниже, следующая команда findсделает это:

find. -type f -name '* (*)*' -exec bash -O extglob -c '
    for pathname do
        filename=${pathname##*/}
        mv -i "$pathname" "${pathname%/*}/${filename// (!(*\)*))}"
    done' bash {} +

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

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

В коде используются три подстановки параметров. Они

  1. ${pathname##*/}:Это отделяет путь к каталогу от имени пути и оставляет только имя файла. В данном случае это то же самое, что и $(basename "$pathaname").

  2. ${pathname%/*}:Это удаляет имя файла из имени пути и оставляет путь к каталогу. В данном случае это то же самое, что и $(dirname "$pathname").

  3. ${filename// (!(*\)*))}":Это специфическаяbash-замена, которая удаляет все пробелы и скобки из значения $filename. Вложенный шаблон -!(*\)*)— это расширенный шаблон подстановки, который соответствует любой строке, не содержащей ). Мы используем это при удалении отдельных круглых скобок, чтобы имя файла, такое как 0 (1) 2 (3)превращается в 0 2, а не только в 0.

Если круглых скобок несколько, все они будут удалены. (, как показано выше ).

Если вы уверены, что у вас нет каталогов с такими круглыми скобками, вы можете использовать более короткую команду

find. -type f -name '* (*)*' -exec bash -O extglob -c '
    for pathname do
        mv -i "$pathname" "${pathname// (!(*\)*))}"
    done' bash {} +

Проверка первой команды:

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Mario Bros (J).nes
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Random game (J,U,E).nes
$ find. -type f -name '* (*)*' -exec prename 's/ \([^)]*\)//g' {} +
$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Mario Bros.nes
-rw-r--r--  1 kk  wheel  0 Mar  6 18:21 Super Random game.nes

Другие команды дают такие же результаты.

1
19.09.2019, 10:32
1 ответ

При использовании шаблона подстановки без кавычек в командной строке оболочка попытается сопоставить его с именами файлов. Если ни одно имя файла не соответствует шаблону, большинство оболочек сохранят нерасширенный шаблон (zsh, который по умолчанию будет жаловаться, как и bashсset -u).

Очевидно, у вас есть какой-то файл, имя которого соответствует *sta*, но не fsta*или *stab. Оболочка расширяет *sta*до имени этого файла, что означает, что шаблон больше не соответствует fstabв /etc.

Решение состоит в том, чтобы использовать одинарные или двойные кавычки вокруг шаблона (и позволить treeвыполнить внутреннее сопоставление с шаблоном ).

5
27.01.2020, 23:15

Теги

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