Как найти файлы по типу файла?

9

Я знаю , что могу найти файлы с помощью find: find . -type f -name 'sunrise'. Пример результата:

./sunrise
./events/sunrise
./astronomy/sunrise
./schedule/sunrise

Я также знаю , что я могу определить тип файла файла: file sunrise. Пример результата:

sunrise: PEM RSA private key

Но как я могу найти файлы по типу файла?

Например, my-find . -type f -name 'sunrise' -filetype=bash-script:

./astronomy/sunrise
./schedule/sunrise
Flux
источник
1
Нет --filetypeопции для команды find или чего-либо еще, что сообщит вам тип файла. Единственное, что вы можете сделать, это использовать --exec file {} \;и затем передать его, grep Bourneесли вы искали bash-скрипты, или grep Perlвы искали Perl-скрипты или что-то в этом роде.
Насир Райли,

Ответы:

13

«Типы файлов» в системе Unix - это такие вещи, как обычные файлы, каталоги, именованные каналы, специальные символьные файлы, символические ссылки и т. Д. Это типы файлов, которые findможно фильтровать с помощью этой -typeопции.

findУтилита не может сам по себе различию между «сценарием оболочкой», «файлом изображения JPEG» или любым другим типом обычного файла . Эти типы данных могут, однако, различаться fileутилитой, которая просматривает конкретные сигнатуры в самих файлах, чтобы определить их тип.

Распространенным способом маркировки файлов данных различных типов является их тип MIME , и fileон может определить тип файла MIME.


Используйте fileс, findчтобы обнаружить тип MIME обычных файлов, и используйте его только для поиска сценариев оболочки:

find . -type f -exec sh -c '
    case $( file -bi "$1" ) in
        */x-shellscript*) exit 0
    esac
    exit 1' sh {} ';' -print

или, используя bash,

find . -type f \
    -exec bash -c '[[ "$( file -bi "$1" )" == */x-shellscript* ]]' bash {} ';' \
    -print

Добавьте -name sunriseперед, -execесли вы хотите обнаруживать только сценарии с этим именем.

Команда findвыше найдет все обычные файлы в или ниже текущего каталога, и для каждого такого файла вызовите короткий встроенный скрипт оболочки. Этот сценарий выполняется file -biдля найденного файла и завершается с нулевым статусом выхода, если выходные данные этой команды содержат строку /x-shellscript. Если вывод не содержит эту строку, он завершается с ненулевым состоянием выхода, что приводит findк немедленному продолжению работы со следующим файлом. Если файл оказался сценарием оболочки, findкоманда продолжит выводить путь к файлу ( -printв конце, который также может быть заменен другим действием).

Команда file -biвыведет MIME-тип файла. Для сценария оболочки в Linux (и большинстве других систем) это будет что-то вроде

text/x-shellscript; charset=us-ascii

в то время как в системах с более старым вариантом fileутилиты, это может быть

application/x-shellscript

Общий бит - это /x-shellscriptподстрока.

Обратите внимание, что в macOS вам придется использовать file -bIвместо file -biиз-за причин ( -iопция делает что-то совсем другое). Вывод на macOS аналогичен выводу системы Linux.


Вы хотели бы , чтобы выполнить некоторые пользовательские действия на каждом сценарии оболочки Found, вы могли бы сделать это с другой -execна месте -printв findкомандах выше, но также было бы возможно сделать

find . -type f -exec sh -c '
    for pathname do
        case $( file -bi "$pathname" ) in
            */x-shellscript*) ;;
            *) continue
        esac

        # some code here that acts on "$pathname"

    done' sh {} +

или, с bash,

find . -type f -exec bash -c '
    for pathname do
        [[ "$( file -bi "$pathname" )" != */x-shellscript* ]] && continue

        # some code here that acts on "$pathname"

    done' bash {} +

Связанные с:

Кусалананда
источник
1

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

# When looking for ASCII Text
find . -type -exec file {} \; | grep "ASCII"
# or for MS Word Documents
find . -type f -exec file {} \; | grep "Microsoft Word"

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

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

Рольф
источник
0

Использование perl«s File::LibMagicмодуля:

perl -MFile::LibMagic=:easy -MFile::Find -le '
  find sub {
    print $File::Find::name if
      $_ eq "sunrise" and
      -f and
      MagicFile$_ eq "PEM RSA private key"
  }, @ARGV' -- .
Стефан Шазелас
источник