您將如何優雅地處理此程式碼段以允許目錄中的空格?
我有一系列命令,例如:
ssh -i key 10.10.10.10 mkdir -p "${DEST_PATH}/subdir1" "${DEST_PATH}/subdir2" rsync "${SOURCE_PATH}" "$DEST_HOST:${DEST_PATH}/subdir1" ...
這些是饋送變數
DEST_PATH=$( myfun "foo" ) SOURCE_PATH=$( myfun "bar" )
這反過來又被餵給字元串
function myfun { local VALUE=$( grep "$1" yadayada.txt | tail -1 | sed 's/someregex//' ) echo "$VALUE" }
你會如何處理
$VALUE
有一些空間……就像 if$VALUE
wasHello World
?我以為總是使用""
可以解決所有問題,但我錯了。其他幾個問題建議轉義或使用單引號,但我不確定最好的解決方法。謝謝
如果您知道遠端系統有一個
xargs
支持-0
選項的命令,您可以執行以下操作:printf '%s\0' "$DEST_PATH/subdir1" "$DEST_PATH/subdir2" | ssh -i key 10.10.10.10 'xargs -0 mkdir -p --'
這段
xargs -0 mkdir -p --
shell 程式碼將被所有 shell 解釋為相同的(記住sshd
在遠端機器上執行遠端使用者的登錄 shell 來解釋給定的程式碼ssh
,可以是任何東西)。的參數列表
mkdir
通過遠端 shell 的標準輸入以 NUL 分隔,由 . 繼承xargs
。這種方法的另一個優點是您可以傳遞任意數量的參數。如果需要,
xargs
將破壞該列表並執行多次呼叫mkdir -p -- dirn dirn+1...
以繞過參數+環境列表的大小限制,甚至可能在為非常大的列表傳輸完整列表之前開始創建目錄。請參閱如何在不知道遠端使用者的登錄 shell 的情況下通過 ssh 執行任意簡單命令?對於其他方法。
rsync
預設情況下,它本身俱有相同的問題,因為它將遠端文件/目錄的名稱作為遠端 shell 命令行的一部分從/到同步傳遞,更好的解決方案是使用-s
/--protect-args
它不是在 shell 程式碼中傳遞文件/目錄名稱,而是在rsync
伺服器的標準輸入上傳遞它。所以:
rsync -s -- "$SOURCE_PATH" "$DEST_HOST:$DEST_PATH/subdir1/"
引用
rsync
手冊頁:如果您需要傳輸包含空格的文件名,您可以指定
--protect-args
(-s
) 選項,或者您需要以遠端 shell 可以理解的方式轉義空格。例如:rsync -av host:'file\ name\ with\ spaces' /dest
$ rsync --rsync-path='set -x; rsync' /etc/issue localhost:'1 2' +zsh:1> rsync --server -e.LsfxC . 1 2 $ rsync --rsync-path='set -x; rsync' /etc/issue localhost:'1;uname>&2' +zsh:1> rsync --server -e.LsfxC . 1 +zsh:1> uname Linux
查看文件名如何解釋為 shell 程式碼。
與
-s
:~$ rsync -s --rsync-path='set -x; rsync' /etc/issue localhost:'1;uname>&2' +zsh:1> rsync --server -se.LsfxC
在遠端 shell 命令行上沒有文件名的痕跡。
~$ cat '1;uname>&2' Ubuntu 20.04.1 LTS \n \l