cmd x>&y
говорит :«перенаправить fd x на любой ресурс, на который перенаправляется fd y»
Так в:
cat 1>&3 3>&1
Вы говорите, что cat
fd 1 (stdout )должен обращаться к тому же ресурсу, что и открытый в fd 3, то есть ./tmp
открыт в режиме чтения+записи; а затем fd 3 на тот же ресурс, что и open на fd 1, который вы только что сделали равным ./tmp
.
Таким образом, cat
будет запущен с обеими fds 1 и 3, перенаправленными на ./tmp
. cat
ничего не делает со своим fd 3, вы можете перенаправить fd 3 cat
на что угодно, это не будет иметь никакого эффекта.
Однако он записывает содержимое file
в свой fd 1, так что вы обнаружите, что содержимое file
записано в начале ./tmp
.
cat file
записывает содержимое file
только один раз и только в один fd. Если вам нужно что-то, что дважды записывает содержимое file
в два разных файла fd, вместо этого вам нужно tee
:
В
< file tee./tmp
tee
будет записывать то, что он читает из своего fd 0 (здесь перенаправлено на file
открыть в режиме чтения -только )в оба./tmp
(открыть в режиме только записи с усечением )и его fd 1 (стандартный вывод ).
Хотя можно сказать tee
открыть ./tmp
в режиме добавления с помощью -a
, вы не можете сказать ему открыть ./tmp
в режиме чтения+записи без усечения, например 3<>
.
Для этого вам понадобится:
< file tee /dev/fd/3 3<>./tmp
, который будет работать, кроме Linux, или прибегнет к использованию zsh
и его встроенной функции ти:
cat < file 3<>./tmp >&1 >&3 3>&-
Если fd 1 перенаправляется дважды, zsh
, когда опция mulltios
включена (включена по умолчанию ), будет выполнять внутренний тройник для пересылки вывода в оба назначения (путем запуска внутренний процесс, который считывает вывод cat
и записывает его в оба адресата ).
Временное использование fd 3 позволяет обойти проблему, которая в
cat < file >&1 1<>./tmp
zsh будет жаловаться на zsh: file mode mismatch on fd 1
, так как предполагается, что вы хотите прочитать из ./tmp
.
jq -R -s '.' < datafile
Это считывает все datafile
как строку, а затем jq просто распечатывает ее как строку JSON. Это даст вам строку в кавычках, подходящую для замены непосредственно в этом шаблоне содержимым datafile
. Данные будут корректно заключены в кавычки JSON -с использованием только escape-последовательности RFC 7159 и будут находиться в одной большой строке, поскольку JSON не позволяет строковым литералам занимать несколько строк.
Вы также можете собрать весь документ в jq с файлом шаблона JSON и
jq --arg f "$(cat datafile)" '.["test.txt"].content = $f' < template.json
В самых последних версиях jq
есть опция --rawfile f datafile
, которую можно использовать для загрузки файла в строку вместо подстановки команд; вы также можете поменять местами -R --slurp --slurpfile t template.json datafile
и t["test.txt"].content =.
.
Мне пришлось экранировать некоторые JSON для включения в другие JSON, и есть очень простое решение:
$ jq @json <<< '{"Hello": "World"}'
"{\"Hello\":\"World\"}"
Если у вас есть документ JSON в file.json
и вы просто хотите вставить содержимое в нужное место, используя jq
,
jq --rawfile content test.txt '."test.txt".content |= $content' file.json
Если содержимое должно быть закодировано в base64 -:
base64 test.txt | jq --rawfile content /dev/stdin '."test.txt".content |= $content' file.json
Создание JSON с нуля с использованиемjo
(аппроксимации метаданных из выходных данных stat
иfile
):
#!/bin/sh
gist_url='some url'
filename=test.txt
jo -p "$filename"="$( jo \
filename="$filename" \
type="$( file -b --mime-type "$filename" )" \
language="$( file -b "$filename" )" \
raw_url="$gist_url" \
size="$( stat -c %s "$filename" )" \
truncated=false \
content=@"$filename" )"
Настройте утилиты stat
и file
в соответствии с вашим Unix (вышеприведенные варианты используют параметры Linux ).
Выход:
{
"test.txt": {
"filename": "test.txt",
"type": "text/x-shellscript",
"language": "POSIX shell script, ASCII text executable",
"raw_url": "some url",
"size": 108,
"truncated": false,
"content": "#!/bin/sh\n\n# comment\nfunc () {\n for ((i=1;i<10;i++)); do\n :\n done\n}\n\nprintf '%s\\n' Foo bar baz"
}
}
Используйте %"$filename"
вместо @"$filename"
, чтобы получить значение в кодировке base64 -для клавиши content
:
{
"test.txt": {
"filename": "test.txt",
"type": "text/x-shellscript",
"language": "POSIX shell script, ASCII text executable",
"raw_url": "some url",
"size": 108,
"truncated": false,
"content": "IyEvYmluL3NoCgojIGNvbW1lbnQKZnVuYyAoKSB7CiAgICBmb3IgKChpPTE7aTwxMDtpKyspKTsgZG8KICAgICAgICA6CiAgICBkb25lCn0KCnByaW50ZiAnJXNcbicgRm9vIGJhciBiYXoK"
}
}