4

Даже после использования Unix-подобных ОС в течение пары лет, это поведение все еще сбивает меня с толку.

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

$ ls
a.txt  C.txt  f.txt  H.txt  k.txt  M.txt  p.txt  R.txt  u.txt  W.txt  z.txt
A.txt  d.txt  F.txt  i.txt  K.txt  n.txt  P.txt  s.txt  U.txt  x.txt  Z.txt
b.txt  D.txt  g.txt  I.txt  l.txt  N.txt  q.txt  S.txt  v.txt  X.txt
B.txt  e.txt  G.txt  j.txt  L.txt  o.txt  Q.txt  t.txt  V.txt  y.txt
c.txt  E.txt  h.txt  J.txt  m.txt  O.txt  r.txt  T.txt  w.txt  Y.txt

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

$ ls | wc
     52      52     312

Другими словами, wc считает, что имеется 52 строки, хотя выход на терминал имеет только 5.

Я не наблюдал такого поведения ни в одной другой команде. Вы хотели бы объяснить это мне?

2 ответа2

8

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

Как обнаружить вывод на терминале: https://stackoverflow.com/questions/1061575/detect-in-c-if-outputting-to-a-terminal

4

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

В этом случае почти всегда удобнее, когда каждая читаемая строка содержит один элемент (1 имя файла) или 1 "запись" информации об одном элементе, а не количество различных элементов, которые должны быть разделить на части.

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

Например ...

Сначала я создаю несколько файлов:

% touch "300"
% cp "300" "301"
% cp "300" "302  304"
% cp "300" "303  305"
% cp "300" "306"
% cp "300" "307"
% cp "300" "308"
% cp "300" "309"
% cp "300" "310  312"
% cp "300" "311  313"
% cp "300" "314  316"
% cp "300" "315  317"
% cp "300" "318"
% cp "300" "319"
% cp "300" "320  322"
% cp "300" "321  323"
% cp "300" "324"
% cp "300" "325"
% cp "300" "bar  bin"
% cp "300" "baz  boo"
% cp "300" "def"
% cp "300" "etc"
% cp "300" "foo  mos"
%

Теперь я получаю "длинный" список файлов, которые я создал:

% ls -l
-rw-r--r-- 1 username username 0 Nov 28 01:51 300
-rw-r--r-- 1 username username 0 Nov 28 01:51 301
-rw-r--r-- 1 username username 0 Nov 28 01:51 302  304
-rw-r--r-- 1 username username 0 Nov 28 01:51 303  305
-rw-r--r-- 1 username username 0 Nov 28 01:51 306
-rw-r--r-- 1 username username 0 Nov 28 01:51 307
-rw-r--r-- 1 username username 0 Nov 28 01:51 308
-rw-r--r-- 1 username username 0 Nov 28 01:51 309
-rw-r--r-- 1 username username 0 Nov 28 01:51 310  312
-rw-r--r-- 1 username username 0 Nov 28 01:51 311  313
-rw-r--r-- 1 username username 0 Nov 28 01:51 314  316
-rw-r--r-- 1 username username 0 Nov 28 01:51 315  317
-rw-r--r-- 1 username username 0 Nov 28 01:51 318
-rw-r--r-- 1 username username 0 Nov 28 01:51 319
-rw-r--r-- 1 username username 0 Nov 28 01:51 320  322
-rw-r--r-- 1 username username 0 Nov 28 01:51 321  323
-rw-r--r-- 1 username username 0 Nov 28 01:51 324
-rw-r--r-- 1 username username 0 Nov 28 01:51 325
-rw-r--r-- 1 username username 0 Nov 28 01:51 bar  bin
-rw-r--r-- 1 username username 0 Nov 28 01:51 baz  boo
-rw-r--r-- 1 username username 0 Nov 28 01:51 def
-rw-r--r-- 1 username username 0 Nov 28 01:51 etc
-rw-r--r-- 1 username username 0 Nov 28 01:51 foo  mos
% 

Хорошо, так что это довольно очевидно, какие имена файлов.

Теперь я получаю список файлов по столбцам:

% ls
300  302  304  306  308  310  312  314  316  318  320  322  324  bar  bin  def  foo  mos
301  303  305  307  309  311  313  315  317  319  321  323  325  baz  boo  etc
% 

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

Если мы передадим вывод ls в more, мы получим:

% ls | more
300
301
302  304
303  305
306
307
308
309
310  312
311  313
314  316
315  317
318
319
320  322
321  323
324
325
bar  bin
baz  boo
def
etc
foo  mos
% 

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .