Странная ошибка «Нет такого файла» с «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 ?

  • копирование подкаталогов, не содержащих определенный файл, в другой каталог
  • GNU parallel vs & (я имею в виду фон) vs xargs -P
  • Понимание -regex с GNU find
  • Возможно ли, чтобы ls поддерживал порядок своих входов
  • Как проверить версию xargs?
  • Grep каталог и возвращаемый список с номерами строк
  • 'find -mtime -1 -print | xargs tar 'архивирует все файлы из каталога, игнорируя аргумент -mtime -1
  • Почему xargs пропускает первый аргумент при передаче в подоболочку?
  • 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

    Макросы командной строки в комментариях с использованием SLURM

    fdisk – по умолчанию для non Dos, но все же использует Dos disklabel

    Как форматировать вывод из nmap в определенном предопределенном формате

    Переместить файл на основе его содержимого

    SSH – соединение закрыто после правильного входа в систему

    Может ли код белого списка Grsec нарушать некоторые его правила?

    Извлечение регулярного выражения, совпадающего с 'sed' без печати окружающих символов

    gajim мигает уведомлением о подносе

    Dropbox – интеграция Nemo под Fedora

    Как избежать ряда подстановочных знаков в сценарии оболочки unix?

    LVM монтирует блокировку ядра

    Замените шаблон, который заканчивается на новой строке тем же шаблоном без новой строки

    Использовать Linux для чтения содержимого зашифрованной папки Windows

    Почему мои виртуальные машины Windows теперь дают мне NS_ERROR_FAILURE при запуске, так как я обновил VirtualBox до 5.1.20?

    Состояние аккумулятора Lenovo T440s неизвестно, но зарядка?

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