Bash

您將如何優雅地處理此程式碼段以允許目錄中的空格?

  • January 20, 2021

我有一系列命令,例如:

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 $VALUEwas Hello 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

引用自:https://unix.stackexchange.com/questions/629925