Fish產生的rsync指令有意想不到的效果

Fish產生的rsync指令有意想不到的效果

我正在使用 Fish shell,並且有一個輔助函數來產生一個 rsync 命令,並設定了所有參數。最終的 rsync 命令應該是這樣的(該命令在一行中,我將其設為多行,因為它更易於閱讀):

rsync -razs -e="ssh -p2222" --update --progress \ 
    --exclude=".*" --exclude="__pycache__" 
    --delete --dry-run \
    $source_dir $dest_dir

從終端來看,它工作正常,但是當我嘗試使用我的輔助函數時,「排除」參數似乎沒有效果。產生的指令看起來完全相同,只是 ssh 指令沒有用引號引起來。但是,這似乎不是問題,因為我可以連接到伺服器。正如我所說,唯一的問題是排除項被忽略。

產生的命令如下所示:

rsync -razs -e=ssh -p2222 --update --progress \
    --exclude=".*" --exclude="__pycache__" \
    --delete --dry-run \
    /home/some_folder user@host:/home/

任何想法?

函數如下所示:

function ssync -d "rsync through ssh tunnel" 

    set origin $argv[1]
    set destination $argv[2]
    set exclude ".*" "__pycache__"

    set ssh_config "ssh -p2222"
    set params -razs -e="$ssh_config" --update --progress --exclude=\"$exclude\"

    if test (count $argv) -gt 2
        set option $argv[3]
        set params $params --delete
        if [ $option = "--delete" ]
            set_color red; echo "Warning: Unsafe run!";
            read -l -P "Confirm? [y/N] " yesno;
            switch $yesno
                case '' N n
                    echo "Sync canceled by user"
                    return 0
                case Y y
                    echo "Proceeding..."
            end
        else
            set params $params --dry-run
        end
    end

    echo "rsync $params $origin $destination"
    rsync $params $origin $destination;
end

[編輯]:感謝 Glenn 的回答,我了解到在函數中使用引號文字是導致問題的原因。但是,它具有非常方便的效果,可以將具有由空格分隔的多個值的參數分隔arg1 arg2為類似--exclude="arg1" --exclude="arg2".有什麼辦法既能帶來好處又不會帶來不便呢?

答案1

您正在新增文字引號字符

... --exclude=\"$exclude\"

這將使 rsync 查找檔案名稱中確實包含引號的檔案。

您只想使用引號將單字括起來

... "--exclude=$exclude"

請記住,引號的目的是指示 shell 以這種方式標記命令想要它。在 shell 實際執行命令之前,實際的引號字元將被刪除。


好的,你有一個清單$exclude 中的項目數。使用大括號代替:示範:

$ set exclude ".*" file1 file2
$ set params --some stuff --other stuff --exclude={$exclude}
$ echo $params
--some stuff --other stuff --exclude=.* --exclude=file1 --exclude=file2

請注意,如果 $exclude 為空,則參數將包含--排除選項:

$ set -e exclude
$ set params --some stuff --other stuff --exclude={$exclude}
$ echo $params
--some stuff --other stuff

相關內容