Объединить вывод двух команд в системе Unix - PullRequest
12 голосов
/ 21 января 2012

Мне нужно объединить вывод двух команд.

Например:

Если я введу ls -l && file *, это даст мне

-rw-rw-r-- 1 user user 1356 2012-01-21 07:45 string.c
-rwxrwxr-x 1 user user 7298 2012-01-21 07:32 string_out
-rw-rw-r-- 1 user user  777 2012-01-18 21:44 test

string.c:   ASCII C program text, with CRLF line terminators
string_out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
test:       POSIX shell script text executable

но я хочу:

-rw-rw-r-- 1 user user 1356 2012-01-21 07:45 string.c string.c:   ASCII C program text, with CRLF line terminators
-rwxrwxr-x 1 user user 7298 2012-01-21 07:32 string_out string_out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
-rw-rw-r-- 1 user user  777 2012-01-18 21:44 test test:       POSIX shell script text executable

Есть предложения, как это сделать?

Ответы [ 5 ]

7 голосов
/ 22 января 2012

У Shiplu есть хорошее простое решение, в bash вы можете сделать это без использования переменных:

for x in *; do 
  echo "$(ls -dl $x) $(file $x)"
done;

Или:

for x in *; do echo "$(ls -dl $x) $(file $x)"; done;

В bash $(cmd) берет вывод cmd и помещает его в командную строку, что очень полезно в подобных ситуациях.

Форма $() может быть менее подвержена ошибкам, чем использование обратных галочек (`cmd`), потому что она безопасно вкладывается:

echo $(ls -l $(which bash))

С помощью обратных кавычек вы должны умножать экранирующие символы, такие как кавычки

5 голосов
/ 22 января 2012

paste ваш друг здесь. Использование замены процесса bash:

paste <(ls -l | sed 1d) <(file *)

edit: добавлена ​​команда sed для удаления первой строки вывода ls ("total: xx")

1 голос
/ 21 января 2012

Вам нужна петля

 for x in *; 
 do 
      ls=`ls -dl $x`
      c=`file $x`
      echo "$ls $c"
 done;

В моем Cygwin нет команды file. Так что я сделал это с wc. Их формат вывода почти одинаков.

$ for x in *; do ls=`ls -l $x`; c=`wc -c $x`; echo "$ls : $c"; done;
-rwxr-xr-x 1 shiplu None 18460 Dec 23 16:27 a.exe : 18460 a.exe
-rw-r--r-- 1 shiplu None 340 Dec 23 16:27 tok.c : 340 tok.c
1 голос
/ 21 января 2012

Использование awk:

awk '
NR==FNR{a[$9":"]=$0;next} 
($1 in a){printf("%-60s\t%-s\n",a[$1],$0)}' <(ls -l) <(file *)

Использование цикла while (аналогично ответу @Shiplu и @ Kyle, но использование while loop с field descriptors:

while read list && read type <&3; do 
   echo "$list $type"; 
done < <(tail +2 <(ls -l)) 3< <(file *)
1 голос
/ 21 января 2012

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

...