Игнорировать все совпадения для отрицательного шаблона extglob в рекурсивном ls

Я хотел бы рекурсивно перечислить все файлы в каталоге, которые соответствуют заданному шаблону ввода, используя ls . (О, и это в Bash).

Единственный способ, с помощью которого я могу сделать это, используя ls, – это использовать shopt -s extglob а затем использовать параметр ls --ignore=pattern с расширенным шаблоном ls --ignore=pattern !( pattern-list ) . Кажется, это круговое движение, чтобы отрицать в игнорировании, но в противном случае маскировки не возвращаются.

Предполагая, что у меня уже есть каталог для поиска в виде dir и шаблона, который соответствует file , это моя текущая попытка:

ls -AR --ignore='!('"${file}"')' ${dir}

Однако, похоже, это не имеет желаемого эффекта, например, в тестовом примере, где структура каталогов дает этот вывод для ls -AR :

  .: a ac b bc c ch s ./s: a ac b bc c ch 

Моя команда с file = *.c и dir = s (полная команда: ls -AR --ignore=!(*.c) s ) дает следующий результат:

  ./s: a ac b bc c ch 

Я знаю, что я могу легко ls -AR s | grep -v '.*.c' его в grep и сделать что-то вроде ls -AR s | grep -v '.*.c' ls -AR s | grep -v '.*.c' и получить вывод, например:

  s: a b c ch 

но я ищу способ сделать это только через ls .

Извините, если я не совсем понял, это мой первый раз на сайте StackExchange.

Заранее спасибо!

2 Solutions collect form web for “Игнорировать все совпадения для отрицательного шаблона extglob в рекурсивном ls”

Как насчет добавления globstar оболочки globstar и флага -d в ls чтобы автоматически не перечислять содержимое каталога?

 shopt -s extglob shopt -s globstar ls -d **/!(*.c) 

--ignore GNU ls --ignore принимает стандартные шаблоны имен файлов, а не расширенный ksh (что bashbash only, not ls ) распознается с помощью extglob )

Таким образом, вы можете:

 ls -AR --ignore='*.[ch]' --ignore='*.cpp' 

Но вы не можете этого сделать:

 ls -AR --ignore='!(*.[ch]|*.cpp)' 

Который бы просто проигнорировал файлы, названные так !(foo.c|bar.cpp) .

В ls -AR --ignore=!(*.c) , поскольку шаблон не цитируется, bash попытается расширить его, прежде чем передать его в ls . Поэтому он будет выглядеть в текущем каталоге для файлов, имя которых начинается с "--ignore=" и не заканчивается на ".c" . Например, если бы было два файла, один из которых назывался --ignore=foo а один – --ignore=bar , он запускал бы ls с этими четырьмя аргументами: "ls" , "-AR" , "--ignore=bar" , "--ignore=foo" .

Вы можете сделать (с GNU find).

 find . -regextype posix-extended -regex '.*\.([ch]|cpp)' -ls 

Или с любым POSIX find :

 find . \( -name '*.[ch]' -o -name '*.cpp' \) -exec ls -ld {} + 

Или, если в каталогах нет ссылок на ссылки:

 shopt -s extglob globstar dotglob failglob ls -ld -- **/*.@([ch]|cpp) 

На этот раз bash расширяет шаблон globbing и передает список файлов в ls .

  • Сколько элементов может хранить массив в unix-скрипте?
  • Как назначить значения матрицы переменным в bash
  • Переменная как команда; eval vs bash -c
  • заменить столбец csv-файла на столбец из другого файла
  • Удаление файлов старше 500 дней
  • Разница в использовании () и $ () для выполнения ряда команд
  • Как мне ожидать «echo -e»? \ С»?
  • Нужна команда для отображения эха «успех»
  • Проблема с символом ':' в скрипте Bash через SSH
  • Задача Cron для удаления файлов старше 3 дней
  • find, xargs и mv: переименование файлов с двойными кавычками, расширение и проблема с приоритетом bash
  • Linux и Unix - лучшая ОС в мире.