Разница между * и pipe

/ dev / zero - это пример «специального файла», в частности, «узла устройства». Обычно они создаются в процессе установки дистрибутива, но вы можете полностью создать их сами, если хотите.

Если вы спросите ls о / dev / zero :

# ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5  Nov 5 09:34 /dev/zero

«c» в начале говорит вам, что это «символьное устройство»; другой тип - «блочное устройство» (печатается ls как «b»). Грубо говоря, устройства с произвольным доступом, такие как жесткие диски, обычно являются блочными устройствами, в то время как последовательные устройства, такие как ленточные накопители или звуковая карта, обычно являются символьными устройствами.

Часть «1, 5» - это «основной номер устройства» и «дополнительный номер устройства».

Имея эту информацию, мы можем использовать команду mknod для создания нашего собственного узла устройства:

# mknod foobar c 1 5

Это создает новый файл с именем foobar в текущей папке, который делает в точности то же самое, что и / dev / zero . (Вы, конечно, можете установить для него разные разрешения, если хотите.) Весь этот «файл» на самом деле содержит три элемента, указанные выше: тип устройства, старший номер, младший номер. Вы можете использовать ls , чтобы найти коды для других устройств и воссоздать их тоже. Когда вам надоест, просто используйте rm , чтобы удалить только что созданные узлы устройств.

В основном старший номер сообщает ядру Linux, с каким драйвером устройства разговаривать, а младший номер сообщает драйверу устройства, о каком устройстве вы говорите. (Например, у вас, вероятно, один контроллер SATA, но, возможно, к нему подключено несколько жестких дисков.)

Если вы хотите изобрести новые устройства, которые делают что-то новое ... ну, вам нужно отредактировать исходный код ядра Linux и скомпилировать собственное ядро. Так что не будем этого делать! :-) Но вы можете добавлять файлы устройств, которые дублируют уже имеющиеся у вас. Автоматическая система, такая как udev, в основном просто отслеживает события устройства и автоматически вызывает mknod / rm . Ничего более волшебного, чем это.

Есть еще другие типы специальных файлов:

  • Linux рассматривает каталог как особый вид файла. (Обычно вы не можете напрямую открыть каталог, но если бы вы могли, вы бы обнаружили, что это обычный файл, который содержит данные в специальном формате и сообщает ядру, где найти все файлы в этом каталоге.)

  • Символьная ссылка - это особый файл. (Но жесткой ссылки нет.) Вы можете создавать символические ссылки с помощью команды ln -s . (Посмотрите справочную страницу для этого.)

  • Также есть вещь, называемая «именованный канал» или «FIFO» (очередь «первым пришел - первым вышел»). Вы можете создать его с помощью mkfifo . FIFO - это волшебный файл, который может быть открыт двумя программами одновременно - одна чтение, одна запись. Когда это происходит, он работает как обычная оболочка. Но вы можете запускать каждую программу отдельно ...

Файл, который ни в коем случае не является «особенным», называется «обычным файлом». Иногда вы можете встретить упоминание об этом в документации Unix. Вот что это значит; файл, который не является узлом устройства, символической ссылкой или чем-то еще. Обычный, повседневный файл без каких-либо магических свойств.

0
25.04.2018, 12:28
2 ответа

Одно верно, другое нет.

du -sh *

(должно быть du -sh -- *, чтобы избежать проблем с именами файлов, начинающимися с-)

полагается на оболочку для расширения шара *; duвидит все не -скрытые файлы и каталоги в текущем каталоге как отдельные аргументы. Это правильно обрабатывает специальные символы.

ls | xargs du -sh

полагается на xargsдля обработки вывода ls. xargsразделяет ввод на пробелы (по крайней мере пробел, табуляция и новая строка, больше с некоторыми реализациями ), также понимает некоторую форму кавычек и запускаетdu(один (даже для пустого ввода¹ )или более вызовов )с каждой отдельной строкой, разделенной пробелами -, в качестве отдельных аргументов.

Оба кажутся эквивалентными, если ваш текущий каталог не содержит файлов с пробелами, одинарными кавычками, двойными кавычками или символами обратной косой черты в их именах, и если файлов достаточно (, но хотя бы один ), который xargsвыполняет только один duвызов, но это не так.

С точки зрения эффективности, du -sh *использует один процесс, ls | xargs du -shиспользует как минимум три. Существует один сценарий, в котором конвейерный подход будет работать, в то время как glob не будет :, если у вас слишком много файлов в текущем каталоге, оболочка не сможет запустить duсо всеми их именами за один раз., но xargsбудет выполняться duстолько раз, сколько необходимо, чтобы охватить все файлы, и в этом случае вы увидите несколько строк, а файлы с более чем одной жесткой ссылкой могут быть учтены несколько раз.

См. также Почему *не *parse `ls `?


¹ Если в текущем каталоге нет скрытого файла, отличного от -, du -sh -- *либо завершится с ошибкой вашей оболочки, либо с некоторыми оболочками, такими как bash, запустите duс литералом *в качестве аргумента и duбудет жаловаться на то, что этот файл *не существует.

В то время как с ls | xargs du -sh --, большинство xargsреализаций (, за исключением некоторых BSD ), будут запускаться duбез аргументов и, таким образом, указывать использование диска в текущем каталоге (, а также включая диск использование самого файла каталога и всех скрытых файлов и каталогов в нем)

11
28.01.2020, 02:13

В первом случае оболочка раскрывает *в список совпадающих имен файлов и передает их в качестве аргументов команде du. Во втором случае оболочка запускает два процесса(lsи xargs), соединенных через конвейер. lsпечатает имена файлов, а xargsчитает их, затем запускает команду du. Итак, вторая версия выполняет 3 команды, первая — только одну. Есть некоторые потенциальные различия:

  • lsможет указывать файлы в другом порядке
  • в зависимости от настроек среды, lsможет даже указывать больше или меньше файлов, (не уверен в этом, хотя)
  • когда xargsполучает больше имен файлов, чем может быть передано в качестве аргументов, он будет выполнять duнесколько раз
1
28.01.2020, 02:13

Теги

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