Intereting Posts
перебирать файлы и отправлять строки в качестве позиционных параметров в другой файл Как исправить ошибку Fontconfig: не удалось прочитать файл конфигурации Как заставить Вино работать с SELinux? Файлы сборки в списке obj-m при создании модулей ядра Как запустить приложение gui framebuffer (no X) при запуске вместо приглашения на вход в консоль? Xkbmap переписывает Xmodmap Установка старых версий пакетов python с apt-get (в частности, wxpython) Практическое руководство. Скрипты Autorun после входа пользователя в систему Bash – Как сократить имя пользователя в PS1 Можно ли удалить префикс папки из команды `ls` Как изменить дату и время последней модификации, независимо от часового пояса и летнего времени? Войти на сайт, используя cURL Как заставить конфликт зависимости для контрольных показателей? Как заставить Linux установить на USB, чтобы показать в Mac Startup Manager? Каковы последствия бездействующего SSH

Получить все файлы, кроме файлов в массиве – Bash

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

Сказав это, как получить имена всех файлов, которые не находятся в данном массиве? Это может быть в любом стандартном скрипте unix (bash, awk, perl).

С помощью bash вы можете сделать:

 all=(*) except=(file1 file2 notme.txt) only=() IFS=/ for file in "${all[@]}"; do case "/${except[*]}/" in (*"/$file/"*) ;; # do nothing (exclude) (*) only+=("$file") # add to the array esac done ls -ld -- "${only[@]}" 

(который работает здесь для файлов в текущем каталоге, но не надежно для globs, таких как all=(*/*) except=(foo/bar) поскольку мы используем / для присоединения к элементам массива для поиска).

Это основано на том факте, что "${array[*]}" объединяет элементы массива с первым символом $IFS (здесь выбрано, чтобы быть / поскольку оно иначе не может иметь место в имени файла, NUL – символ что не может произойти в пути к файлу, но, к сожалению, bash (в отличие от zsh ) не может иметь такой символ в своих переменных). Итак, для каждого файла в $all (здесь в качестве примера используется $file foo ), мы делаем case "/file1/file2/notme.txt/" in (*"/foo/"*) чтобы проверить, является ли $file быть исключенным.

С zsh проще:

 except=(file1 file2 notme.txt) all=(*) only=(${all:|except}) ls -ld -- $only 

Мнемоника для ${all:|except} : элементы $all bar имеют значение $except .

Вы также можете проверить, находятся ли файлы в массиве $except как часть классификатора glob :

 ls -ld -- *.txt(^e:'((except[(Ie)$REPLY]))':) 

Или используя функцию:

 in_except() ((except[(Ie)${1-$REPLY}])) ls -ld -- *.txt(^+in_except) 

Если имена файлов достаточно просты, вы можете использовать переменную GLOBIGNORE от GLOBIGNORE :

GLOBIGNORE оболочки GLOBIGNORE может использоваться для ограничения набора имен файлов, соответствующих шаблону. Если установлено GLOBIGNORE , каждое совпадающее имя файла, которое также соответствует одному из шаблонов в GLOBIGNORE , удаляется из списка совпадений. Если параметр nocaseglob установлен, сопоставление с шаблонами в GLOBIGNORE выполняется независимо от случая. Имена файлов . и .. всегда игнорируются при установке GLOBIGNORE а не в GLOBIGNORE . Однако установка GLOBIGNORE в значение, GLOBIGNORE от нуля, приводит к включению dotglob оболочки dotglob , поэтому все остальные имена файлов начинаются с dotglob ' . 'будет соответствовать. Чтобы получить старое поведение игнорирования имен файлов, начинающихся с символа ' . ', сделайте' .* 'один из шаблонов в GLOBIGNORE . Опция dotglob отключается, когда GLOBIGNORE работает.

 $ echo * bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin srv sys tmp usr var $ except=(etc lib lib64 tmp sbin) $ GLOBIGNORE=$(IFS=:; printf "%s" "${except[*]}") $ echo * bin boot dev home lost+found mnt opt proc root run srv sys usr var 

Конечно, если вы создаете массив, то вместо этого вы можете напрямую установить переменную GLOBIGNORE :

 GLOBIGNORE=etc:lib:lib64:tmp:sbin 

Вы также можете воспользоваться любыми шаблонами, которые могут быть в списке, которые соответствуют шаблонам bash:

 GLOBIGNORE=etc:lib*:tmp:sbin