在 Bash 脚本中正确转义正斜杠以便与 sed 一起使用

在 Bash 脚本中正确转义正斜杠以便与 sed 一起使用

我尝试通过在干模式下运行 rsync,然后计算 rsync 输出中列出的文件大小,来确定同步两个文件夹时新复制的文件的大小。

目前,我无法使用父文件夹为文件添加前缀。我找到了如何使用 sed 为行添加前缀以及如何使用 sed 进行转义,但我在将这两者结合起来时遇到了麻烦。

这是我取得的进展:

source="/my/source/folder/"
target="/my/target/folder/"
escaped=`echo "$source" | sed -e 's/[\/&]/\\//g'`
du `rsync -ahnv $source $target | tail -n +2 | head -n -3 | sed "s/^/$escaped/"` | awk '{i+=$1} END {print i}'

这是我从 bash -x myscript.sh 获得的输出

+ source=/my/source/folder/
+ target=/my/target/folder
++ echo /my/source/folder/
++ sed -e 's/[\/&]/\//g'
+ escaped=/my/source/folder/
+ awk '{i+=$1} END {print i}'
++ rsync -ahnv /my/source/folder/ /my/target/folder/
++ sed 's/^//my/source/folder//'
++ head -n -3
++ tail -n +2
sed: -e expression #1, char 8: unknown option to `s'
+ du
80268

如果您能提供任何关于如何正确逃脱的想法,我们将不胜感激。

答案1

你实际上不需要费心去转义/。从GNUsed手册

任何给定命令中的字符/都可以被任何其他单个字符统一替换s

例如:

echo 'foobar' | sed -e 's#foo#bar#'

给出输出

barbar

答案2

如果您尝试汇总数据,则可能希望跳过任何可能的子目录。这可能不适用,但最好始终避免任何奇怪的情况。这是我的源目录。这些文件都是使用 touch 创建的,因此它们占用 0 空间。

$ find source
source
source/5832
source/5832/5832_1.png
source/5832/5832_2.png
source/5831
source/5831/5831_1.png
source/5830
source/5830/5830_3.png
source/5830/5830_1.png
source/5830/5830_2.png

您不需要像现在这样在任何地方进行转义。此处的 sed 块将执行以下操作:
1d;删除“发送增量文件列表”的第一行
/^$/,$d;删除表示文件列表结束的空白行及其后的所有内容。//$/d
删除以“/”结尾的任何行,即目录请
注意,您可以使用反斜杠转义斜杠(以回答实际问题)。

$ du $(rsync -ahnv source target | sed '1d;/^$/,$d;/\/$/d')
0   source/5830/5830_1.png
0   source/5830/5830_2.png
0   source/5830/5830_3.png
0   source/5831/5831_1.png
0   source/5832/5832_1.png
0   source/5832/5832_2.png

为了获得额外的奖励积分,你甚至可以把结果加起来:

$ du -s $(rsync -ahnv source target | sed '1d;/^$/,$d;/\/$/d') | awk '{x+=$1;print $0} END {print "sum: "x}'
0   source/5830/5830_1.png
0   source/5830/5830_2.png
0   source/5830/5830_3.png
0   source/5831/5831_1.png
0   source/5832/5832_1.png
0   source/5832/5832_2.png
sum: 0

但是,如果您在目录已完全同步的情况下执行此操作,它将返回有趣的结果:

76  .
sum: 76

相关内容