Почему команда «ls | файл »работа?

Я изучал командную строку и узнал, что | (конвейер) предназначен для перенаправления вывода команды на ввод другой. Так почему же команда ls | file не работает?

file input является одним из нескольких имен файлов, например file filename1 filename2

ls output является списком каталогов и файлов в папке, поэтому я подумал, что ls | file должен показывать тип файла каждого файла в папке.

Однако, когда я его использую, вывод будет:

    Usage: file [-bcEhikLlNnprsvz0] [--apple] [--mime-encoding] [--mime-type]
        [-e testname] [-F separator] [-f namefile] [-m magicfiles] file ...
    file -C [-m magicfiles]
    file [--help]

Так как произошла ошибка при использовании команды file

32
задан 13 July 2016 в 09:49

8 ответов

Фундаментальная проблема в том, что file ожидает имена файлов в качестве аргументов командной строки, а не на stdin. При записи ls | файла вывод ls передается как входной файл . Не как аргументы, а как входные.

Какая разница?

  • Аргументы командной строки - это когда вы пишете флаги и имена файлов после команды, как в cmd arg1 arg2 arg3. В скриптах командной строки эти аргументы доступны в виде переменных $1, $2, $3 и др. На языке Си они доступны через аргументы char **argv и int argc к main().

  • Стандартный вход, stdin, представляет собой поток данных. Некоторые программы, такие как cat или wc, читают из stdin, когда им не заданы аргументы командной строки. В скрипте оболочки можно использовать read для получения одной строки ввода. В C вы можете использовать scanf() или getchar(), среди различных опций.

file обычно не читается из stdin. Он ожидает, что в качестве аргумента будет передано по крайней мере одно имя файла. Поэтому он распечатывает использование при записи ls | file, потому что вы не передали аргумент.

Вы могли бы использовать xargs для преобразования stdin в аргументы, как в ls | xargs file. Тем не менее, как упоминает terdon, парсинг ls - плохая идея. Самый прямой способ сделать это - просто:

file *
71
ответ дан 13 July 2016 в 09:49
  • 1
    Большое спасибо за Вашу справку, это - более важное знание, чем голоса. – Alvaro Niño 1 February 2018 в 22:54

узнал, что '|' (pipeline) предназначен для того, чтобы перенаправить вывод из команды на ввод другой.

Он не "перенаправляет" вывод, а берет вывод программы и использует его как ввод, в то время как файл берет не вводы, а имена файлов в качестве аргументов, которые затем тестируются. Переадресация не передает эти имена файлов в качестве аргументов, как это делает piping, чем позже вы это сделаете.

Что вы можете сделать, так это прочитать имена файлов из файла с опцией --files-from, если у вас есть файл, который перечисляет все файлы, которые вы хотите протестировать, в противном случае просто передайте пути к вашим файлам в качестве аргументов.

6
ответ дан 13 July 2016 в 09:49
  • 1
    Тонкая настройка ПОМОЩНИКА несколько раз отказывала на мне, который может быть частью проблемы, но установкой макета панели к " Ubuntu MATE" кажется, решил проблему. Это также поливает из шланга большую работу, которую я сделал на панели и настройках секции, но ничем это can' t быть воссозданным. Marco (наборщик программного обеспечения) является значением по умолчанию/нейтрализацией WM и был уже установлен этот путь. Спасибо! – Lindsay Haisley 31 January 2018 в 08:59

Принятый ответ объясняет, почему команда трубопровода не работает сразу, а с помощью команды файла * он предлагает простое, простое решение.

Я хотел бы предложить другую альтернативу, которая может пригодиться в какой-то момент. Хитрость в том, чтобы использовать символ (`). Здесь бэктик объяснен очень подробно. Короче говоря, он берет вывод команды, заключенной в бэктик, и заменяет его как строку на оставшуюся команду. Итак, find `ls` получит вывод команды ls, и подставить его в качестве аргументов для команды find. Это длиннее и сложнее принятого решения, но варианты этого могут быть полезны и в других ситуациях.

6
ответ дан 13 July 2016 в 09:49
  • 1
    Установлен ли рабочий стол помощника человечности с помощью склонного - достигают CLI, или использование Синаптического PM не важно, по крайней мере, в этом случае. Позади UI это выполняет то же самое. Тонкая настройка ПОМОЩНИКА показывает знаки неаккуратного программирования. Это несколько раз отказывало на мне, как это, по-видимому, имеет для других. Это делает , позволяют поднимать запас макет панели ПОМОЩНИКА Ubuntu, который решил проблему меню и вручную восстановление моей работы конфигурации панели wasn' t настолько трудный. Снова, спасибо за регулирование меня в правильном направлении. – Lindsay Haisley 2 February 2018 в 12:20

Вывод ls через канал представляет собой сплошной блок данных с размером 0x0a, разделяющий каждую строку - т.е. символ linefeed - и file получает его как один параметр, где ожидает работу нескольких символов по одному за раз.

Как правило, никогда не используйте ls для генерации источника данных для других команд - в один прекрасный день он обрушится ... на rm и тогда у вас будут проблемы!

Лучше использовать цикл, например для i в *; do file "$i"; done, который выдаст нужный вам результат, предсказуемо. Там кавычки в случае имен файлов с пробелами.

5
ответ дан 13 July 2016 в 09:49
  • 1
    Хороший для замечания вот то, что это - активная версия Ubuntu, который может или не может позволить Вам сохранять и использовать файлы. – Robby1212 31 January 2018 в 08:03

Потому что, как вы говорите, на вход файла должны быть введены имена файлов . Однако вывод ls - это всего лишь текст. То, что это список имен файлов, не меняет того факта, что это просто текст, а не расположение файлов на жестком диске.

Когда вы видите вывод, напечатанный на экране, вы видите только текст. Является ли этот текст стихотворением или списком имён файлов, не имеет никакого значения для компьютера. Все, что он знает, это то, что это текст. Вот почему вывод ls можно передать программам, которые принимают текст за ввод (хотя вы действительно, действительно не должны ):

$ ls / | grep etc
etc

Итак, чтобы использовать вывод команды, которая перечисляет имена файлов в виде текста (например, ls или find) как ввод для команды, которая принимает имена файлов, вам нужно использовать некоторые хитрости. Типичным инструментом для этого является xargs:

$ ls
file1 file2

$ ls | xargs wc
 9  9 38 file1
 5  5 20 file2
14 14 58 total

Как я уже говорил ранее, на самом деле вы не хотите разбирать вывод ls. Что-то вроде find лучше (print0 печатает \0 вместо newilne после имени каждого файла и -0 из xargs позволяет иметь дело с таким вводом; это уловка, чтобы заставить ваши команды работать с именами файлов, содержащими новые строки):

$ find . -type f -print0 | xargs -0 wc
 9  9 38 ./file1
 5  5 20 ./file2
14 14 58 total

Который также имеет свой собственный способ сделать это, вообще не требуя xargs:

$ find . -type f -exec wc {} +
 9  9 38 ./file1
 5  5 20 ./file2
14 14 58 total

Наконец, вы также можете использовать цикл оболочки. Однако, обратите внимание, что в большинстве случаев xargs будет намного быстрее и эффективнее. Например:

$ for file in *; do wc "$file"; done
 9  9 38 file1
 5  5 20 file2
18
ответ дан 13 July 2016 в 09:49
  • 1
    Этот doesn' t, кажется, проблема установки. Посмотрите мое ре примечания. эта проблема, являющаяся определенным для пользователя, не в масштабе всей системы. – Lindsay Haisley 31 January 2018 в 08:48

Она работает с помощью команды, как показано ниже

ls | xargs file

Она будет работать лучше для меня

2
ответ дан 13 July 2016 в 09:49
  • 1
    Для современного BIOS, который действительно загружается от USB; нет. Это было бы медленнее для начинающих. – Hannu 5 February 2018 в 01:12

Если вы хотите использовать канал для передачи файла , используйте опцию -f, за которой обычно следует имя файла, но вы также можете использовать один дефис - для чтения из stdin, Поэтому

$ ls
cow.pdf  some.txt
$ ls | file -f -
cow.pdf:       PDF document, version 1.4
some.txt:        ASCII text

Трюк с дефисом - работает со многими стандартными утилитами командной строки (хотя иногда это --), так что всегда стоит попробовать.

Инструмент xarg намного мощнее и в большинстве случаев нужен только в том случае, если список аргументов слишком длинный (подробности см. в -).

4
ответ дан 13 July 2016 в 09:49
  • 1
    I' ve, пытаясь загрузить Ubuntu на карту с интерфейсом USB для загрузки на ноутбук Toshiba для использования в качестве моей ОС, потому что это не имеет никакого диска ROM. Было бы лучше получить диск ROM вставить его и загрузить его из CD? – Steve 4 February 2018 в 08:01

Это также должно работать:

file $(ls)

, как также обсуждается здесь: https://unix.stackexchange.com/questions/5778/whats-the-difference-between-stuff- и прочее

1
ответ дан 13 July 2016 в 09:49
  • 1
    Спасибо за Ваш ответ. Начальная загрузка от режима восстановления (усовершенствованные опции человечности) работала, теперь я могу войти в систему. Но право преимущественной покупки ' ubuntu' все еще имеет проблему. Версия ядра 4.4.0-111-универсальна. И когда я пытался найти, какой видеодрайвер я использую, там прибывает предупреждение, которое говорит - ' необходимо запустить эту программу как супер user' и ниже этого большая информация, но никакое название драйвера там. – Meem 3 February 2018 в 01:17

Другие вопросы по тегам:

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