gpt4 book ai didi

Bash 转义波浪号和通配符但不转义空格

转载 作者:行者123 更新时间:2023-11-29 09:06:29 24 4
gpt4 key购买 nike

(使用 sed 在解决方案中编辑)

我有一个文件名和目录列表,包括波浪号和通配符。例如:

~/docs/file.*    
~/my docs/*.txt
...

我读取行并将它们传递给命令(例如 rsync):

while read ROW
do
rsync $ROW /my/dest/
done < list.txt

问题是处理文件名中的空格。如果我像这样将 $ROW 放在双引号中

rsync "$ROW" /my/dest/

当然,bash 不会逃避通配符或波浪号。但是,如果我不使用引号,空格会换行。

一种可能的解决方案是更改 IFS(小心:脚本比我报告的脚本更复杂)。另一个解决方案(感谢对 Patrick Echterbruch 的修复)是预转义空间。但是,以下代码对我不起作用:

while read ROW
do
export NEWROW=$(echo $ROW | sed -e 's/ /\\ /g')
echo "Value: $NEWROW"
ls -1d $NEWROW
done < list.txt

请注意没有引号传递给 ls。文件“~/a b c/test.txt”存在,但我得到:

Value: ~/saver/a\ b\ c/*.txt
ls: impossibile accedere a ~/saver/a\: Nessun file o directory
ls: impossibile accedere a b\: Nessun file o directory
ls: impossibile accedere a c/*.txt: Nessun file o directory

似乎 NEWROW 被作为字符串传递给 ls,因此通配符没有扩展,但空格不断破坏文件名,尽管已转义。

有什么建议吗?谢谢。

最佳答案

据我所知,您发布的 sed 脚本不会有任何效果 - “搜索”和“替换”部分是相同的。

你可以做什么:

ROW=$(echo $ROW | sed -e "s/ /\\\\ /g")

或(更好):

ROW=$(echo $ROW | sed -e 's/ /\\ /g')

后一个示例使用单引号,因此 shell 不会特殊处理反斜杠。

关于出现的第二个问题:特殊字符(如~)在程序参数中遇到时会被bash 扩展。将它们存储在变量中时不会扩展它们,bash 也不会在将变量作为参数传递给命令时检查和扩展变量的内容。

这就是为什么 rsync $NEWROW ... 不起作用 - rsync 接收 $NEWROW 的未修改内容作为第一个参数,然后必须自己进行类似 shell 的扩展。

我知道的唯一解决方法是在子 shell 中运行命令,即:

ROW="~/a b c"
$NEWROW=$(echo $ROW | sed -e 's/ /\\ /g')
bash -c "ls -ld $f"

这将导致当前运行的 bash 提取变量内容(即 ~/a\b\c 并将其传递给它即将调用的第二个 shell。这个“内部”bash 将接收命令连同参数,然后当然会进行参数扩展。

很抱歉一开始就忽略了这一点,我只关注问题的正则表达式部分。

找到另一个可能的解决方案:使用 sed 转换路径后(例如 NEWROW=$(echo $ROW | sed -e 's//\\/g') 尝试:

eval ls -ld $NEWROW

或者 eval rsync $NEWROW/other/path

这应该也能正常工作,不会影响启动子 shell 的性能。

//编辑:将缺少的 g 添加到 sed 脚本

//编辑:添加路径名扩展问题的解决方法

//编辑:添加评估解决方案

关于Bash 转义波浪号和通配符但不转义空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4722817/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com