Спецификация POSIX дает вам пример для этого:
ls | sed -e 's/"/"\\""/g' -e 's/.*/"&"/' | xargs -E '' printf '<%s>\n'
(с именами файлов, представляющими собой произвольные последовательности из байтов (, отличных от /
и NULL )и sed
/ xargs
, ожидающих текста , вам также необходимо исправить локаль на C (, где все не -байты NUL будут действительными символами ), чтобы сделать это надежным (, за исключением xargs
реализаций, которые имеют очень низкий предел максимальной длины аргумента ))
. ]
-E ''
необходим для некоторых xargs
реализаций, которые без него понимали бы аргумент _
для обозначения конца ввода (, где echo a _ b | xargs
выводит a
только для примера ).
С GNU xargs
вы можете использовать:
ls | xargs -d '\n' printf '<%s>\n'
GNU xargs
также имеет -0
, который был скопирован несколькими другими реализациями, поэтому:
ls | tr '\n' '\0' | xargs -0 printf '<%s>\n'
немного более портативный.
Все они предполагают, что имена файлов не содержат символов новой строки. Если могут быть имена файлов с символами новой строки, вывод ls
просто не будет обрабатываться после -. Если вы получите:
a
b
Это могут быть либо два файла a
и b
, либо файл с именем a
, точно сказать невозможно.
GNU ls
имеет --quoting-style=shell-always
, который делает его вывод однозначным и может обрабатываться после -, но цитирование несовместимо с цитированием, ожидаемым xargs
. xargs
распознают "..."
, \x
и '...'
формы цитирования. Но и "..."
, и '...'
являются сильными кавычками и не могут содержать символы новой строки. (только \
может экранировать символы новой строки для xargs
),так что это несовместимо с цитированием sh, где только '...'
являются сильными кавычками (и могут содержать символы новой строки ), но \
является продолжением строки -(удаляется )вместо экранированной новой строки.
Вы можете использовать оболочку для разбора этого вывода, а затем вывести его в формате, ожидаемомxargs
:
eval "files=($(ls --quoting-style=shell-always))"
[ "${#files[#]}" -eq 0 ] || printf '%s\0' "${files[@]}" |
xargs -0 printf '<%s>\n'
Вам необходимо экранировать $
перед $HOSTNAME
переменной (или командой $(hostname)
), чтобы она разворачивалась/запускалась на удаленной машине, а не на локальной:
#!/bin/bash
while read PASSWORD SERVER;do
sshpass -p "$PASSWORD" ssh -t -p 1234 $SERVER << EOF
wget -N https://example.com/file.conf 2>&1 | grep -i "failed\|error\|saved"
sed -i "s/variabletoreplace/\$HOSTNAME/" file.conf
EOF
done
Как упоминалось в комментариях, было бы намного лучше использовать ключи ssh, а не sshpass
, и если бы все эти команды, которые вы хотите запустить, находились в сценарии на удаленном хосте, это было бы намного проще. В качестве альтернативы может быть более подходящим использование такого инструмента, как ansible
или puppet
.