Странная ошибка «Нет такого файла» с «xargs» и «file»

Я хотел бы получить MIME-тип всех файлов в текущем каталоге. Почему это не работает? Я тестировал bash на OSX или Linux. «file» жалуется, что он не может найти файл, но если я запустил его с тем же самым путем, он работает.

$ find . -type f | xargs -n 1 -I FILE echo $(file --mime-type -b FILE) ERROR: cannot open './foo.txt' (No such file or directory) ... $ file --mime-type -b ./foo.txt text/plain 

Конечно, в реальном мире я не просто «отгоняю» ответ, мне нужно использовать строку типа MIME в другой команде.

Это самое простое, что я мог бы решить эту проблему. Думаю, я не понимаю что-то о xargs имени файла xargs ?

  • Печать состояния файлов, обрабатываемых при использовании find
  • Команда xargs приводит к sed:;: Нет такого файла или каталога
  • Передача списка из двух PID для xargs только убивает первый, используя ssh
  • Как перемещаться по xargs, где каждый скрипт использует общую переменную env
  • Найти, сочетание xargs и grep вызывает ошибку
  • Сколько способов конвертировать и передавать stdin в качестве параметра команды?
  • Ускорение команды поиска rm с проверкой путем распараллеливания
  • xargs -r0 vs xargs -0
  • 3 Solutions collect form web for “Странная ошибка «Нет такого файла» с «xargs» и «file»”

    Командная подстановка $(file --mime-type -b FILE) выполняется оболочкой перед передачей xargs , поэтому вы не видите, что вам нужно. Ответить $(file --mime-type -b FILE) и передать его в bash -c через xargs

     find . -type f | xargs -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)' 

    Здесь нет необходимости использовать xargs . Просто используйте переключатель find -s -exec .

     $ find . -type f -exec file --mime-type -- {} + 

    Примеры

    вывод file умолчанию

     $ find 8* -type f -exec file --mime-type -- {} + | tail -5 89999/sample10.txt: text/plain 89999/sample2.txt: text/plain 89999/sample4.txt: text/plain 89999/sample6.txt: text/plain 89999/sample9.txt: text/plain 

    file -b вывод

     $ find 8* -type f -exec file --mime-type -b -- {} + | head -5 application/x-empty text/x-perl text/plain text/plain text/plain 

    альтернативы

    Это всего лишь FYI, но есть еще одна команда под названием mimetype которую вы также можете использовать для того, чтобы сделать то же самое, что и file --mimetype . Эта команда является частью этого пакета в Fedora, perl-File-MimeInfo и работает аналогично:

     $ find 8* -type f -exec mimetype -- {} + | tail -5 89999/sample10.txt: text/plain 89999/sample2.txt: text/plain 89999/sample4.txt: text/plain 89999/sample6.txt: text/plain 89999/sample9.txt: text/plain 

    Более сложный exec

    Учитывая, что вы задавались вопросом о том, что «делать больше, чем просто эхо …», и поскольку вы пытаетесь использовать xargs я собираюсь сделать вывод, что вы думаете, что вам нужно будет сделать более подробную информацию с xargs .

    Но если вы используете find , это, как правило, не самый лучший способ. Вместо этого вы можете использовать find , а затем в find -s -exec коммутаторе вызывать оболочку и делать здесь более сложные вещи, а не пытаться уговорить xargs делать это сложнее.

     $ find . -type f -exec sh -c ' cmd1; cmd2; file --mime-type -b "$@"; cmd3; cmd4; ' sh {} \; 

    ПРИМЕЧАНИЕ. Я перешел от использования терминатора + который передает несколько аргументов в file --mime-type ... to \; который проходит один за раз.

    пример

     $ find 8* -type f -exec sh -c ' echo -n "mime-type: "; file --mime-type -b "$@" ' sh {} \; |& tail -10 mime-type: text/plain mime-type: text/plain mime-type: text/plain mime-type: text/plain mime-type: text/x-shellscript mime-type: text/plain mime-type: text/plain mime-type: text/plain mime-type: text/plain mime-type: text/plain 

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

    Кроме того, если вы обрабатываете имена файлов, привыкайте использовать print0 и 0, как их оставляете, это создаст проблемы для вас с именами файлов, содержащими пробельный символ.

    Пример:

     find . -type f -print0 | xargs -0 -n 1 -I FILE bash -c 'echo $(file --mime-type -b FILE)' 

    В вашем случае это может быть упрощено:

     find . -type f -print0 | xargs -0 -n 1 file --mime-type -b 

    Дополнительный комментарий: вызов программы для всех найденных файлов (будь то «xargs -n 1» или find + exec) может стать настоящим узким местом производительности. Если у вас есть каталог с тысячами файлов, вы создадите тысячи процессов.

    Interesting Posts

    Что на самом деле убивает 0?

    Невозможно установить libevent без прав администратора

    Какие правила определяют отношения между родителями и дочерними процессами, запущенными оболочкой через трубу?

    Как обновляется так много быстрее, чем найти?

    Как установить openssh-сервер на моем сервере?

    AWK с спецификацией: Есть ли классный способ обработки спецификации Unicode с регулярным выражением?

    Удаление диска из RAID

    Звуковая передача SoundWire, но без звука

    Как использовать sed для замены строки, используя номер строки на удаленной машине, используя ssh?

    Каковы альтернативы GNU ld?

    QEMU 2.8.0-r1 с vfio VGA passthrough на Gentoo 4.8.17-hardened-r2 зависает при перезагрузке Radeon RX 480

    Резервное копирование определенного пакета и его зависимостей

    Удалите все строки под определенным номером строки из одного столбца

    Как печатать удобочитаемый формат в формате KB, MB, GB вместо K, M, G?

    Системный образ запущенной системы Debian?

    Linux и Unix - лучшая ОС в мире.