Предположим, что у Вас есть переменные server
и dir
определенный, можно сделать
$ dir="~"
$ server="user@server.com"
$ scp $server:$dir/$(ssh $server 'ls -t $dir | head -1') .
Где Вы сначала ищете новейший файл и затем копируете его.
Примечание: Я не проверял его на надежность (например, при этом последняя запись была папкой),
Для этой цели я обычно определяю функцию типа run
. В большинстве случаев она может корректно обрабатывать споры с пробелами и прочими.
#!/bin/bash
run() {
if $DEBUG; then
v=$(exec 2>&1 && set -x && set -- "$@")
echo "#${v#*--}"
"$@"
else
"$@" >/dev/null 2>&1
fi
}
DEBUG=false
run echo "bla"
DEBUG=true
run echo "bla"
run printf "%s . %s . %s\n" bla "more bla" bla
Вывод:
$ bash debug.sh
# echo bla
bla
# printf '%s . %s . %s\n' bla 'more bla' bla
bla . more bla . bla
В вашем случае эхо обрабатывают $ Redir
как строковый аргумент. Тем не менее, вы хотите что-то вроде:
~$ echo "bla" >/dev/null 2>&1
~$ REDIR='>/dev/null 2>&1'
~$ eval "echo bla $REDIR"
~$
, если вы не пытаетесь сделать быстрое и грязное взломать, Weouter Verhelst имеет лучшее решение (и это действительно не так долго или сложно).
Перенаправление не является командой, поэтому вы не можете выполнить ее таким образом. Вы можете сделать это, если вы используете EVAL
, но это открывает банку червей.
Лучший способ сделать то, что вы пытаетесь сделать, это иметь функцию для отладки вывода:
function debugprint {
if [ ! -z "$debug" ]; then
echo "$1"
fi
}
debugprint "$(echo 'bla' 2>&1)"
Это будет перенаправить стандартную ошибку на стандартный выход, а затем вызов DebugPrint
с выходом в виде аргумент Теперь все, что вам нужно сделать, это установить $ Debug
к чему-то непустому, когда вы хотите отладить.
Конечно, это также открытие (разные) банки червей (связанных с цитированием). Возможно, вы захотите просто использовать SET -X
вместо этого, который может или не может сделать достаточно для ваших потребностей отладки.
возможно, вы могли бы использовать функцию для конвейерного вывода вывода и позволить ему выполнять перенаправление:
#! /bin/bash
DEBUGMODE="Debug"
function handleStdOut {
if [[ "$DEBUGMODE" == "Debug" ]]
then
echo "Debugging..."
cat
echo "Done"
else
cat > /dev/null
fi
}
echo "bla" | handleStdOut
Для каждой функции оболочки, которую я пишу, я делаю то же самое.
fn(){
echo some normal stderr debug stuff >&2 #if $DBG 2>stderr
dd if="\$DBG/please/report/on/this/file" #ditto
echo I DEFINITELY need to handle this >&3 #always stderr
( PATH=; ".some" oops I expect to handle ) 2>&4 #always /dev/null
echo and the regular stuff #always unaffected
} 4<>/dev/null 3>&2 2>&"$((${#DBG}?3:4))"
Мне это нравится по нескольким причинам.
Использование оценки $ {# DBG}
для len всегда гарантирует целочисленное значение > = 0 для теста - независимо от того, что $ DBG
может на самом деле содержать. Это делает математические вычисления безопасными, например, если DBG = IFS = 0
.
Каждый раз, когда функция запускается, она должна выполнять только фактическую open ()
на / dev / null
один раз - в любой другой раз я перенаправляю на / dev / null
Я делаю это с установленным дескриптором в #fd> & 4
.
Вывод отладки - как я мог бы включить с помощью set -x
- для функций в моих интерактивных оболочках сбрасывается по умолчанию , если я явно не установил переменную среды $ DBG
на любое ненулевое значение.
$ DBG
не является нулевым, математическое расширение для перенаправления будет указывать на себя - оно оценивается как 2> & 3
. 2> & 4
и переходит к открытому дескриптору / dev / null
. ~ / .sh / fn / ...
, но команда -строка, в которой он участвует, - это, вероятно, совсем другое дело, если я установил -x
. $ DBG
имеет значение null / не установлено, но set -x
включен , поскольку он открывает выход eval для каждой команды в $ PS4
, который не попадает в stderr, но #fd> & 3
все еще может попасть туда. Это разрешает наследование разумным способом.
$ DBG
, что может позволить им начать запись в stderr по умолчанию, если это уже невозможно. $ DBG
не установлен или обнулен, все дочерние функции, которые он вызывает, теряют даже значение # fd3
, если только он не вызывает их с помощью child_fn 2> & 3
- в этом случае они получат ту же возможность, что и их родитель, для явной записи в stderr. $ DBG
, чтобы отключить эти дочерние функции, даже если $ DBG
уже установлен. $ DBG
, чтобы функции верхнего уровня, вызываемые после , включали вывод stderr по умолчанию. Я сохраняю копию stderr на #fd> & 3
, и поэтому, если функция должна, она все равно может писать в stderr явно на этот дескриптор (кроме случаев, указанных выше) .
Дескрипторы закрываются и не влияют на текущие значения оболочки для fds 2, 3, 4, потому что они связаны только с составной командой, которая является оболочкой для функции.
{3,4}> & -
никогда не требуется.