Как передать строку команде, которая ожидает файл? [дубликат]

На своей платформе Debian я обнаружил, что в процессе установки Microsoft ODBC libodbc.so помещается в / usr / lib64 . Это неподходящее место для библиотек, и bcp не может его найти. Но вместо того, чтобы сказать вам, что он не может найти необходимую библиотеку, он просто выходит.

Решение для Debian. Ваша ситуация должна быть похожей.

  1. Найдите, куда процедура установки поместила libodbc.so :

     find / -type f -name libodbc.so 
     
  2. Добавить его каталог в новый файл /etc/ld.so.conf.d/odbc.conf . Я придумал это имя, и в моей системе /etc/ld.so.conf.d включен из /etc/ld.so.conf :

     # Обязательно но не задокументировано установкой MS ODBC для SQL Server 
     / usr / lib64 
     
  3. Запустите ldconfig , чтобы обновить список расположений библиотек

  4. Повторите попытку bcp command

Для выполнения шагов 2 и 3 вам понадобится root. Я полагаю, что в этом нет ничего страшного, учитывая, что вам удалось установить библиотеки SQL Server.

33
12.03.2019, 12:27
4 ответа

Еще один способ использования функции подстановки процесса -оболочки bashвызывает создание FIFO в /tmpили /var/tmpили использование именованного файлового дескриптора (/dev/fd/*), в зависимости от операционной системы. система. Синтаксис подстановки(<(cmd))заменяется именем FIFO или FD, а команда внутри него выполняется в фоновом режиме.

cook <(printf '%s\n' "${the_recipe}")

Команда cookтеперь считывает содержимое переменной, как если бы оно было доступно в файле.

Это также можно использовать для более чем одного входного файла:

cook <(printf '%s\n' "${the_1st_recipe}") <(printf '%s\n' "${the_2nd_recipe}")
47
27.01.2020, 19:37

Вы можете использовать «поддельное» имя файла /dev/stdin, которое представляет собой стандартный ввод.

Итак, выполните это:

echo "$the_recipe" | cook /dev/stdin

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

57
27.01.2020, 19:37

Это зависит от возможностей приложения. Он может настаивать или не настаивать на именованном файле, а может и не настаивать на доступном для поиска файле.

Анонимный канал

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

printf '%s' "$the_recipe" | cook     # passes $the_recipe exactly
printf '%s\n' "$the_recipe" | cook   # passes $the_recipe plus a final newline

Не используйте здесь echo, потому что в зависимости от оболочки это может исказить обратную косую черту.

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

printf '%s\n' "$the_recipe" | cook -

Если приложению требуется фактическое имя файла, передайте /dev/stdinдля обозначения стандартного ввода.

printf '%s\n' "$the_recipe" | cook /dev/stdin

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

Именованный канал

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

mkfifo named.pipe
printf '%s\n' "$the_recipe" >named.pipe & writer=$!
cook named.pipe
rm named.pipe
wait "$writer"

(Проверка ошибок не выполняется.)

Временный файл

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

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

cook <<<"$the_recipe"

При использовании других оболочек или если вы хотите указать, в какой директории находится временный файл, вам необходимо создать временный файл вручную. Большинство Unix предоставляют утилитуmktempдля безопасного создания временного файла. (Никогда не используйте что-то вроде… >/tmp/temp.$$! Это позволяет другим программам, даже работающим от имени других пользователей, перехватывать файл. )Вот сценарий, создающий временный файл и удаляющий его в случае прерывания.

tmp=
trap 'rm -f "$tmp"' EXIT
trap 'rm -f "$tmp"; trap "" HUP; kill -INT $$' HUP
trap 'rm -f "$tmp"; trap "" INT; kill -INT $$' INT
trap 'rm -f "$tmp"; trap "" TERM; kill -INT $$' TERM
tmp=$(mktemp)
printf '%s\n' "$the_recipe" >"$tmp"
cook "$tmp"

Чтобы выбрать место для создания временного файла, установите переменную среды TMPDIRдля вызова mktemp. Например, чтобы создать временный файл в текущем каталоге, а не в месте по умолчанию для временных файлов:

tmp=$(TMPDIR="$PWD" mktemp)

(Использование $PWDвместо .дает вам абсолютное имя файла, что означает, что вы можете безопасно вызывать cdв своем скрипте, не беспокоясь о том, что $tmpбольше не будет обозначать тот же файл.)

Если приложению требуется имя файла с определенным расширением, необходимо создать временный каталог и создать там файл. Чтобы создать временный каталог, используйте mktemp -d. Опять же, установите переменную среды TMPDIR, если вы хотите контролировать, где создается временный каталог.

tmp=
trap 'rm -rf "$tmp"' EXIT
trap 'rm -rf "$tmp"; trap "" HUP; kill -INT $$' HUP
trap 'rm -rf "$tmp"; trap "" INT; kill -INT $$' INT
trap 'rm -rf "$tmp"; trap "" TERM; kill -INT $$' TERM
tmp=$(mktemp -d)
printf '%s\n' "$the_recipe" >"$tmp/myfile.ext"
cook "$tmp/myfile.ext"
25
27.01.2020, 19:37

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

echo "$the_recipe" | cook -

или

cook - <<<"$the_recipe"
3
27.01.2020, 19:37

Теги

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