Nar*_*ico 5 bash filenames space escaping
(用sed编写解决方案)
我有一个文件名和目录列表,包括代字号和通配符.例如:
~/docs/file.*
~/my docs/*.txt
...
Run Code Online (Sandbox Code Playgroud)
我读取行并将它们传递给命令(例如rsync):
while read ROW
do
rsync $ROW /my/dest/
done < list.txt
Run Code Online (Sandbox Code Playgroud)
问题是处理文件名中的空格.如果我把$ ROW放在这样的双引号中
rsync "$ROW" /my/dest/
Run Code Online (Sandbox Code Playgroud)
当然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
Run Code Online (Sandbox Code Playgroud)
请注意,没有引号传递给ls.文件"〜/ abc/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
Run Code Online (Sandbox Code Playgroud)
似乎NEWROW作为字符串传递给ls,因此通配符不会被扩展,但是空间会不断地破坏文件名,但是会被转义.
有提示吗?谢谢.
据我所知,您发布的 sed 脚本不会产生任何效果 - “搜索”和“替换”部分是相同的。
你能做的可以做:
ROW=$(echo $ROW | sed -e "s/ /\\\\ /g")
Run Code Online (Sandbox Code Playgroud)
或更好):
ROW=$(echo $ROW | sed -e 's/ /\\ /g')
Run Code Online (Sandbox Code Playgroud)
后一个示例使用单引号,因此 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"
Run Code Online (Sandbox Code Playgroud)
这将导致当前运行的 bash 提取变量内容(即将~/a\ b\ c其传递给即将调用的第二个 shell)。这个“内部”bash 将接收命令和参数,然后当然会进行参数扩展。
很抱歉一开始就错过了这一点,我只关注问题的正则表达式部分。
找到了另一种可能的解决方案:使用 sed 转换路径后(例如NEWROW=$(echo $ROW | sed -e 's/ /\\ /g')尝试:
eval ls -ld $NEWROW
Run Code Online (Sandbox Code Playgroud)
或 eval rsync $NEWROW /other/path
这应该也能正常工作,而不会影响启动子 shell 的性能。
//编辑:将缺失添加g到 sed 脚本中
//编辑:添加了路径名扩展问题的解决方法
//编辑:添加评估解决方案
| 归档时间: |
|
| 查看次数: |
1784 次 |
| 最近记录: |