如何用反斜杠和 space "\ " 替换 space 以便 bash shell 脚本可以从 .tsv 文件中读取文件名并执行 rsync 复制

How to replace a space with backslash and space "\ " so bash shell script can read the file name from a .tsv file and perform rsync copy

我有一个脚本,它从由 space 分隔的 tsv 文件中获取源和目标信息。第一列表示源文件路径,第二列是目标。我的 rsync 命令读取源和目标信息并执行复制操作。

但问题是源文件和目标文件都包含带有白色 space (header-background copy.jpg) 的文件名,而我们知道当 bash shell读取文件名(带space),它将space替换为反斜杠后跟space“\”

/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background copy.jpg /mapped-data/data20/data3/header-background copy.jpg

我的问题是如何将 space 替换为“\”,以便 shell 可以读取它。我尝试使用下面的 sed 命令

sed -r 's/^\s+//;s/\s+/\ /g' test2.tsv

但是有一个问题,上面的 sed 命令还在源路径后面添加了一个反斜杠。正如我所提到的,我的脚本从 .tsv 文件中获取源和目标信息,因此添加斜杠在这里是一个问题。下面是 sed 命令的输出。

/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background\ copy.jpg\ /mapped-data/data20/data3/header-background\ copy.jpg

我想要的是隐蔽的东西

/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background copy.jpg /mapped-data/data20/data3/header-background copy.jpg

/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background\ copy.jpg /mapped-data/data20/data3/header-background\ copy.jpg

tsv file separated by space

至少使用 tab,因为 tabspace.

更不可能出现在路径中

备注:你知道吗只有/[=17=](NULL byte) 是 Linux 文件系统中文件名的禁用字符?这意味着除 [=17=] 之外的所有内容都可以出现在路径中...

假设您的文件现在是 tab 定界的,并且您的路径不包括 newlinestabs。 BASH:

阅读方法
while IFS=$'\t' read -r filepath1 filepath2
do
    declare -p filepath1 filepath2
done <<< "/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background copy.jpg"$'\t'"/mapped-data/data20/data3/header-background copy.jpg"

输出:

declare -- filepath1="/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background copy.jpg"
declare -- filepath2="/mapped-data/data20/data3/header-background copy.jpg"

如果你需要明确地转义一个变量(例如在scprsync的远程部分)那么你可以使用printf '%q' 像这样:

rsync -av "$filepath1" user@server:"$(printf '%q' "$filepath2")"

使用 sed,一种方法是将匹配项分组,然后 return 使用附加反斜杠的反向引用

sed 's/\([A-Za-z0-9\/][^\.]*\) /\ /g' input_file
/data-prod/bigdata/abc/test/1143-1003-004_1143-1003-905/static/common/images/header-background\ copy.jpg   /mapped-data/data20/data3/header-background\ copy.jpg

使用参数替换拆分列:

while IFS= read -r line; do
    # count raw tabs to validate format
    tabs=${line//[!$'\t']}
    tabs=${#tabs}

    if ((tabs!=1)); then
        echo "${line//$'\t'/TAB}: less or more than one raw tab, skipping…" >&2
    else
        # split by tab
        source=${line%$'\t'*}
        target=${line#*$'\t'}

        rsync "$source" "$target"
    fi

done < list.tsv

循环检查每一行是否只有一个制表符,如果没有则跳过。添加您的 rsync 选项等

确保列表没有符号转义字符(如 \t\n),或任何其他不属于文字文件名的 escapes/quotes。 tsvcsv 可以有各种不同的非文字引用,需要正确解析。

另请注意 rsync 的用法,用于将文件名从列表文件复制到单个目标:rsync [opts] —files-from="my-source-list" /my/target/