Объединить вывод двух команд в системе unix

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

Например:

Если я ввешу 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

Любые предложения, как это сделать?

Ответ 1

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 и помещает его в командную строку, что очень полезно для таких ситуаций.

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

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

С обратными выводами вы должны умножать escape-элементы, например, кавычки

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

Вам нужен цикл

 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

Ответ 5

Использование 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 *)