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

  • Как выполнить итерацию списка и скопировать файлы из machineB и machineC эффективно?
  • Как скопировать три файла одновременно, а не один файл за один раз в сценарии оболочки bash?
  • Команда, которая дает имя пользователя @ hostname: pwd
  • Как запустить веб-страницу в фоновом режиме?
  • / bin / dash: проверьте, является ли $ 1 числом
  • Debian: настройка пути для узла с правами доступа, доступными глобально
  • Это самое простое, что я мог бы решить эту проблему. Думаю, я не понимаю что-то о xargs имени файла xargs ?

  • Удалить соответствующий файл из каждой подпапки текущего каталога
  • Bash: Как читать по одной строке за один раз из вывода команды?
  • grep целые блоки файловой системы на устройствах
  • Сценарий Bash не будет работать в текущем каталоге
  • изменить строку и удалить тег, используя perl из xml-файла?
  • Как начать работу с bash?
  • 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) может стать настоящим узким местом производительности. Если у вас есть каталог с тысячами файлов, вы создадите тысячи процессов.

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