Каков эффективный способ автоматического добавления расширений к файлам без расширений?

Нет, главным образом по той причине, что не требуется, чтобы системы соответствовали по умолчанию или соответствовали только стандарту POSIX (исключение любого другого стандарта ).

Например, Solaris (, сертифицированная совместимая система ), выбрала обратную совместимость для своих утилит в /bin, что объясняет, почему они ведут себя загадочным образом, и предоставляют совместимые с POSIX -утилиты в разных местах (/usr/xpg4/bin. ], /usr/xpg6/bin... для различных версий XPG (, теперь объединенных со стандартом POSIX ), которые фактически являются частью необязательных компонентов в Solaris ).

Даже shне обязательно будет в /bin. В Solaris /bin/shраньше была оболочкой Bourne (, поэтому она не совместима с POSIX )до Solaris 10, а теперь ksh93 в Solaris 11 (все еще не полностью совместима с POSIX, но на практике в большей степени, чем /usr/xpg4/bin/sh).

Из С,вы можете использовать exec*p()и предположить, что вы находитесь в среде POSIX (, в частности, в отношении PATHпеременной среды ).

Вы также можете установить переменную окружения PATH

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);

Или вы можете определить во время сборки путь к утилитам POSIX, которые вы хотите запустить (, имея в виду, что в некоторых системах, таких как системы GNU, вам потребуются дополнительные шаги, такие как установка POSIXLY_CORRECTпеременной для обеспечения соответствия ).

Вы также можете попробовать:

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);

В надежде, что в $PATHесть sh, что он похож на -Борна, что также есть getconfи что он подходит для интересующей вас версии POSIX.

2
03.11.2021, 22:33
2 ответа

for x in $(find …) не работает с именами файлов, содержащими пробелы (общие )или подстановочные знаки (несколько необычные). Никогда не анализируйте вывод find. Используйте -exec.

Zsh 'szmvудобен для массового переименования.

Давайте создадим команду zmv, которая будет делать то, что вы хотите. Во-первых, давайте построим шаблон поиска:

autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
  • -Cзаставляет файлы копироваться, а не перемещаться.
  • -o -aпереходит от -aк cp.
  • -nозначает не действовать, просто напечатать то, что будет сделано. Удалите его, как только вы будете счастливы. Замените его на -v, если вы хотите действовать, но также печатать то, что делается.
  • -Qвключает квалификаторы glob в шаблоне.
  • (*/)#соответствует нулю или более каталогам. Он использует оператор глобуса#(extended_glob, который всегда включен в zmv ).
  • ^*.*использует оператор glob ^для сопоставления файлов без .в их имени.
  • (.)— это квалификатор glob, который ограничивает совпадения с обычными файлами.
  • будет заменен текстом замены. Это может использовать $fдля ссылки на исходное имя.

zmvвычисляет все замещающие имена перед выполнением какой-либо замены и выдает сообщение, если какое-либо замещающее имя уже существует или возникают конфликты. Файлы, для которых замещающее имя идентично исходному, пропускаются.

Теперь создадим замещающий текст. Мы будем использовать множество расширений параметров .

  1. Запросите у fileдобавочный номер:$(file --extension --brief -- $f)
  2. Добавить .для подготовки к замене:$(echo -n.; file --extension --brief -- $f)
    (В качестве альтернативы это можно сделать с помощью расширения параметра:${:-.$(…)}.)
  3. Если предложено несколько расширений (, разделенных косой чертой ), оставить только первое:${$(echo -n.; file --extension --brief -- $f)%%/*}
  4. Если предложенный добавочный номер пуст или ???,отказаться от (заменить .или .???пустой строкой):${${$(echo -n.; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
  5. Добавить добавленное расширение к$f(исходному имени ). Если то, что мы добавляем, пусто, файл останется нетронутым.

Результирующая команда:

zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n.; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'

Это немного загадочно, и вы можете предпочесть поместить код для генерации замены в функцию и использовать zmv … '$(add_extension $f)'.

2
04.11.2021, 15:14

Я думаю, что наиболее эффективным способом является сравнение mime-типов -файла с базой данных, расположенной по адресу /usr/share/mime/globs.

  • globs в Linux имеют расширение файла . Приведен пример, вывод из файла globs
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
  • после описания примера типа --> text/x-erlang, он указывает Linux идентифицировать все файлы *.как Erlang с расширением .erl[glob], поэтому -->*.erl
  • вы можете добавить свои собственные расширения для учета в файле /etc/magic

поэтому запустив команду:

mimetype -bM file
  • bаргумент в пользу просто покажу вамtype-app/extension(кратко)

  • Аргумент
  • Mозначает Магия — это способ, с помощью которого Linux проверяет файл в байтовом, шестнадцатеричном, двоичном коде, чтобы убедиться, что файлы действительно являются теми, за кого себя выдают.

  • mimetype не возвращает /jpg/png/webpвозвращает только один тип, и он короче, чемfile --mime-type file

Возвращает:

image/webp

последние мысли

mimetypeлучше всего работает с двоичными файлами , такими как PDF-файлы, изображения, видео. Это потому, что он может проверять двоичный файл, вместо этого text plain- это просто, и вам нужно с чем-то идентифицировать, а это сложнее, поэтому текстовые редакторы могут реконизировать разные языки программирования, ему нужна помощь пользователя и язык сервера для каждого языка программирования.

для рекурсии, я думаю дерево подходит:

tree -FIi '*.*' | grep -v /$
  • аргумент Fдля добавления /[косая черта] к каталогам, например, folderfolder/
  • аргумент I— выбор противоположного шаблону *.*[это означает выбор всех файлов с расширением],так что противоположное не является расширением
  • аргумент i— удалить пробелы из вывода дерева
  • grep -vозначает выбор реверса, поэтому вы добавляете аргумент -F /к команде tree в начале, чтобы вы могли удалять каталоги и получать только файлы с помощью /$.

Подробнее здесь MIME-типы

1
10.11.2021, 00:33

Теги

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