Запустите две команды по одному аргументу (без скриптов)

Как я могу выполнить две команды на одном входе без ввода этого ввода дважды?

Например, команда stat много рассказывает о файле, но не указывает его тип файла:

stat fileName 

Команда file указывает, какой тип файла:

 file fileName 

Вы можете выполнить это в одной строке следующим образом:

 stat fileName ; file fileName 

Однако вам нужно дважды ввести имя_файла.

Как вы можете выполнять обе команды на одном и том же входе (без ввода ввода или переменной ввода дважды)?

В Linux я знаю, как обрабатывать выходные данные, но как вы подключаете входы?

10 Solutions collect form web for “Запустите две команды по одному аргументу (без скриптов)”

Вот еще один способ:

 $ stat filename && file "$_" 

Пример:

 $ stat /usr/bin/yum && file "$_" File: '/usr/bin/yum' Size: 801 Blocks: 8 IO Block: 4096 regular file Device: 804h/2052d Inode: 1189124 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Context: system_u:object_r:rpm_exec_t:s0 Access: 2014-06-11 22:55:53.783586098 +0700 Modify: 2014-05-22 16:49:35.000000000 +0700 Change: 2014-06-11 19:15:30.047017844 +0700 Birth: - /usr/bin/yum: Python script, ASCII text executable 

Это работает в bash и zsh . Это также работает в mksh и dash но только в интерактивном режиме. В AT & T ksh это работает только тогда, когда file "$_" находится в другой строке от stat .

Вероятно, чтобы получить, чтобы мои костяшки постучали по этому поводу, вот хакерская комбинация расширения бреша и eval, которая, кажется, делает трюк

 eval {stat,file}" fileName;" 

С помощью zsh вы можете использовать анонимные функции:

 (){stat $1; file $1} filename 

С es lambdas:

 @{stat $1; file $1} filename 

Вы также можете сделать:

 { stat -; file -;} < filename 

(сначала выполнив stat как file обновит время доступа).

Я сделаю:

 f=filename; stat "$f"; file "$f" 

хотя это переменные.

Все эти ответы кажутся мне сценарием, в большей или меньшей степени. Для решения, которое действительно не содержит сценариев, и предполагает, что вы сидите за клавиатурой, набрав ее в оболочку, вы можете попробовать:

 stat somefile Введите
 file Esc _ Введите

В bash, zsh и ksh, по крайней мере, в режимах vi и emacs, нажатие Escape, а затем подчеркивание вставляет последнее слово из предыдущей строки в буфер редактирования для текущей строки.

Или вы можете использовать замену истории:

 stat somefile Введите
 file! $ Enter

В bash, zsh, csh, tcsh и большинстве других оболочек !$ Заменяется последним словом предыдущей командной строки при анализе текущей командной строки.

То, как я нашел это достаточно просто, это использовать xargs, он принимает файл / трубу и преобразует его содержимое в аргументы программы. Это можно комбинировать с tee, который разбивает поток и отправляет его двум или более программам. В вашем случае вам нужно:

 echo filename | tee >(xargs stat) >(xargs file) | cat 

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

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

РЕДАКТИРОВАТЬ

Как было предложено в комментариях, в этом ответе есть несколько недостатков, во-первых, это потенциал для чередования выходных данных. Это можно зафиксировать так:

 echo filename | tee >(xargs stat) >(( wait $!; xargs file )) | cat 

Это заставит команды работать поочередно, и выход никогда не будет чересстрочным.

Вторая проблема заключается в том, чтобы избежать замещения процесса, который недоступен в некоторых оболочках, этого можно добиться, используя tpipe вместо tee:

 echo filename | tpipe 'xargs stat' | ( wait $!; xargs file ) 

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

Этот ответ похож на пару других:

 stat filename && file! #: 1

В отличие от других ответов, которые автоматически повторяют последний аргумент из предыдущей команды, это требует от вас подсчета:

 ls -ld filename && file! #: 2

В отличие от некоторых других ответов, это не требует котировок:

 stat "useless cat" && file !#:1 

или

 echo Sometimes a '$cigar' is just a !#:3. 

Я думаю, вы задаете неправильный вопрос, по крайней мере, за то, что вы пытаетесь сделать. stat и file принимают параметры, которые являются именем файла, а не его содержимым. Позднее команда выполняет чтение файла, идентифицируемого именем, которое вы указываете.

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

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

Это должно работать для всех имен файлов в текущем каталоге.

 sh -c "$(printf 'stat -- "$1";file -- "$1";shift%.0b\n' *)" -- * 

Здесь есть несколько разных ссылок на «ввод», поэтому я дам несколько сценариев, понимая это в первую очередь. Для быстрого ответа на вопрос в кратчайшей форме :

 stat testfile < <($1)> outputfile 

Вышеприведенное будет выполнять stat на тестовом файле, принимать (перенаправлять) его STDOUT и включать его в следующую специальную функцию (часть <()), а затем выводить окончательные результаты того, что было, в новый файл (выходной файл). Файл вызывается, а затем ссылается на встроенные модули bash ($ 1 каждый раз после того, как вы начнете новый набор инструкций).

Ваш вопрос велик, и есть несколько ответов и способов сделать это, но он действительно меняется с тем, что вы делаете конкретно.

Например, вы можете также зацикливать это, что весьма удобно. Общепринятое использование этого в мышлении psuedo-code – это:

 run program < <($output_from_program)> my_own.log 

Принимая это и расширяя это знание, вы можете создавать такие вещи, как:

 ls -A; (while read line; do printf "\e[1;31mFound a file\e[0m: $line\n"; done) < <(/bin/grep thatword * | /usr/bin/tee -a files_that_matched_thatword) 

Это приведет к простому ls -A в вашем текущем каталоге, а затем сообщит, когда будет проходить каждый результат от ls -A до (и вот где это сложно!) Grep «theword» в каждом из этих результатов и выполнять только предыдущие printf (красным), если он действительно нашел файл с «этим словом» в нем. Он также регистрирует результаты grep в новом текстовом файле, files_that_matched_thatword.

Пример вывода:

 ls -A; (while read line; do printf "\e[1;31mFound a file\e[0m: $line\n"; done) < <(/bin/grep thatword * | /usr/bin/tee -a files_that_matched_thatword) index.html 

Все это просто напечатало результат ls -A, ничего особенного. Добавьте что-нибудь для этого grep на этот раз:

 echo "thatword" >> newfile 

Теперь запустите его:

 ls -A; (while read line; do printf "\e[1;31mFound a file\e[0m: $line\n"; done) < <(/bin/grep thatword * | /usr/bin/tee -a files_that_matched_thatword) files_that_matched_thatword index.html newfile Found a file: newfile:thatword 

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

Это похоже на пару других ответов, но более переносимо, чем этот, и намного проще, чем этот :

 sh -c 'stat "$ 0";  file "$ 0" ' filename

или

 sh -c 'stat "$ 1";  файл "$ 1" 'sh filename

в которой sh присваивается значение $0 . Хотя это еще три символа, эта (вторая) форма предпочтительнее, потому что это $0 – это имя, которое вы даете этому встроенному скрипту. Он используется, например, в сообщениях об ошибках для оболочки для этого скрипта, например, когда file или stat не могут быть найдены или не могут быть выполнены по какой-либо причине.


Если вы хотите сделать

 stat filename 1 filename 2 filename 3 ...;  file filename 1 filename 2 filename 3 ...

для произвольного количества файлов, сделайте

 sh -c 'stat "$ @";  file "$ @" 'sh filename 1 filename 2 filename 3 ...

который работает, потому что "$@" эквивалентен "$1" "$2" "$3" …

  • Почему моя команда mmv не перезаписывает файлы?
  • Прокрутка вывода команды без временного файла
  • Внедрение оболочки Unix в C: Logging
  • Как создать пустой PDF-файл из командной строки?
  • Настройка прозрачного представления через файловый менеджер nautilus
  • Копирование файлов на несколько компьютеров по локальной сети
  • Поиск источника и источника копирования для плоской цели
  • Как перечислить только последнюю строку каждого каталога?
  • Выполнить команду после каждой выходной строки из команды ping
  • почему вывод xargs -n2 применяется к тому же количеству аргументов, различающихся по каналам или с клавиатуры?
  • Как я могу воспроизвести команды, запущенные на одной машине на другой машине?
  • Linux и Unix - лучшая ОС в мире.